调试版本SEGFAULT而发布版本有效-是RVO吗
Debug version SEGFAULTs whereas Release version works - is it RVO?
我们有一个模板类,它拥有一些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_;
};
它有两个构造函数,我们制作了一个包装器函数,据说它可以简化事情:
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...);
}
我们中的两个人已经在Ubuntu 16.04上测试过了,G++5.9和Boost 1.58。当我们构建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
,并最终通过此路由被复制。
根据经验,可以用一个参数调用的构造函数(可能是在添加默认值之后)应该是explicit
。
BTW:你的另一个ctor也有一个逻辑错误:
template <typename... parameters>
callable(callback functor,
platform info = default_node,
parameters... args);
这个默认值将如何使用?只有在提供了一个参数的情况下才能使用它,但随后会出现过载解析,并选择第一个ctor。也就是说,它也是当前形式的一个潜在的单参数ctor,也应该是explicit
。
- 欧拉项目#8答案是大以获得有效答案
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 导入库可以跨dll版本工作吗
- 调整大小后指向元素值的指针unordered_map有效?
- 为什么是0;C++中的有效语句
- 最高有效数字侧的第N位
- GCC对可能有效的代码抛出init list生存期警告
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 有效地使用std::unordered_map来插入或增加键的值
- c++中O(n^(1/3))中一个数的除数的有效计数
- 使用无符号字符数组有效存储内存
- 自定义先决条件对移动分配运算符有效吗
- 在clang++预处理器中确定gcc工具链版本
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 不同的Visual Studio版本中缺少.dll
- 基于布尔标志有效地派生公共函数的两个版本
- 调试版本SEGFAULT而发布版本有效-是RVO吗
- 为什么 qDebug 在发布版本中有效
- 无论CRT版本如何,这都是在库中提供STL函数的有效方法吗
- 无法使用迭代器遍历字符串:但是我的带有索引的版本确实有效