gpt4 book ai didi

c++ - 调试版本 SEGFAULTs 而发布版本有效 - 是 RVO 吗?

转载 作者:太空狗 更新时间:2023-10-29 21:34:20 26 4
gpt4 key购买 nike

我们有一个模板类,它拥有一些 std::unique_ptr,其中一些是 boost::asio

template <class cloud_type,
bool keep_alive = true,
class socket_type = asio_http,
class error_handle = default_error_handler>
class callable
{
callable() = delete;
// other stuff here, click the link to see actual code
private:
// other members, most are unique pointers
std::unique_ptr<boost::asio::io_service> io_;
};

它有two constructors我们制作了一个包装函数,据称可以简化事情:

template <class cloud_type,
bool keep_alive = true,
class socket_type = asio_http,
class error_handle = default_error_handler,
class ...args,
typename =
typename std::enable_if<!std::is_same<cloud_type,
cloud_batch>::value, bool>>
callable<cloud_type,keep_alive,socket_type,error_handle>
call(typename cloud_type::callback functor,
args... params)
{
return callable<cloud_type,
keep_alive,
socket_type,
error_handle>(functor, default_node, params...);
}

我们中的两个人已经在带有 G++ 5.9 和 Boost 1.58 的 Ubuntu 16.04 上对此进行了测试。当我们构建一个 Release 版本(使用 -O3)时,应用程序工作正常。但是,当我们构建一个 Debug 版本时,应用程序会出现 SEGFAULT。我得到的实际错误是:

Thread 1 "human_detection" received signal SIGSEGV, Segmentation fault.
0x0000000000443128 in std::unique_ptr<boost::asio::io_service, std::default_delete<boost::asio::io_service> >::get (this=0x120) at /usr/include/c++/5/bits/unique_ptr.h:305
305 { return std::get<0>(_M_t); }

这似乎源于:

#0  0x0000000000443128 in std::unique_ptr<boost::asio::io_service, std::default_delete<boost::asio::io_service> >::get (this=0x120) at /usr/include/c++/5/bits/unique_ptr.h:305
#1 0x0000000000441880 in std::unique_ptr<boost::asio::io_service, std::default_delete<boost::asio::io_service> >::operator-> (this=0x120) at /usr/include/c++/5/bits/unique_ptr.h:298
#2 0x000000000043f2b4 in noos::cloud::callable<noos::cloud::human_detection, false, noos::cloud::asio_http, noos::cloud::default_error_handler>::send (this=0x0, timeout=0) at /home/zuperath/code/noos-api-maria/./noos/cloud/callable.tpl:120

指向:

void callable<cloud_type,
keep_alive,
socket_type,
error_handle
>::send(unsigned int timeout)
{
assert(socket_ && query_ && resol_ && io_);
if (!socket_)
throw std::runtime_error("socket not set");
if (!io_ || !query_ || !resol_)
throw std::runtime_error("io, query or resolver not set");
object.fill_buffer(boost::ref(*buffer_.get()), endpoint);
socket_->is_connected() ?
socket_->send(*query_.get(), *resol_.get(), timeout, *buffer_.get()) :
socket_->begin(*query_.get(), *resol_.get(), timeout);
io_->run();
io_->reset(); // here !!!
}

我试图了解我们做错了什么,我猜测 Release 使用 RVO,而 Debug 制作了一个拷贝,导致上述结果?

当我调用包装器时:

auto query = call<human_detection,false>(
[&](std::vector<noos::object::human> humans) {
std::cout << "Found " << humans.size() << " humans!" << std::endl;
}, pic);

错误在 Debug 期间仍然存在,而如果我直接调用类构造函数,SEGFAULT 就会消失:

callable<human_detection,false> query([&](std::vector<noos::object::human> humans) {
std::cout << "Found " << humans.size() << " humans!" << std::endl;
}, default_node, pic);

我担心的是类的资源(例如,boost::asio::io)存在潜在问题,这是通过创建类来实现的可复制。

编辑:

我解决了 SEGFAULT,这是由于通过引用捕获的 lambda,一个正在发布的 (this)。但是,我原来的问题仍然存在;为什么在 DEBUG 期间发生这种情况而不是在 RELEASE 期间发生?

最佳答案

复制 unique_ptr 当然有一个基本问题,这是不可能的。这就是独特的意义所在。编译器通过禁用其复制构造函数来强制执行此操作。因此 callable 的默认复制构造函数也不存在。

但它确实看起来您的callable 可以被复制。我怀疑发生的事情是你不小心写了一个转换构造函数:

callable::callable(callback functor, platform = default_node);

我怀疑您的 callable 可以转换为 callback 并最终通过此路由被复制。

根据经验,可使用一个参数调用的构造函数(可能在添加默认值之后)应该是显式

顺便说一句:您的其他 ctor 也有逻辑错误:

template <typename... parameters>
callable(callback functor,
platform info = default_node,
parameters... args);

究竟如何使用这个默认值?它只能在提供单个参数的情况下使用,但随后会启动重载决策并选择第一个 ctor。也就是说,它在当前形式下也是一个潜在的单参数构造函数,也应该是显式

关于c++ - 调试版本 SEGFAULTs 而发布版本有效 - 是 RVO 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46911813/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com