std::函数析构函数中的Segfault
Segfault in std::function destructor
我目前正在维护一个用C++开发的C++REST服务器。它提供了一些功能,如中间件和路由。
路由存储在路由器类的内部结构中:
//! The http router
//!
//! allow us to parse route on a server using regex to match the good route for a given url
//! and extract the possible url variables
class router {
private:
//! routes datas
//!
//! contains:
//! * the regex to parse the routes
//! * an std::vector with the list of variable inside the routes
//! * 4 std::function, one for each REST methods
struct rest_routes {
std::regex regex;
std::vector<std::string> vars_name;
std::pair<std::function<http::response(http::request&)>, std::vector<std::string>> get;
std::pair<std::function<http::response(http::request&)>, std::vector<std::string>> post;
std::pair<std::function<http::response(http::request&)>, std::vector<std::string>> put;
std::pair<std::function<http::response(http::request&)>, std::vector<std::string>> del;
};
};
在执行过程中一切都很好:可以配置路由并将其添加到路由器中,如果有人在现有路由上请求服务器,则会执行回调,服务器会按预期发送响应。
下面是一个路由配置的例子,我们为HTTP DELETE
请求创建一个路由/admin/cameras/:cam_id
:
// delete a camera
router.del("/admin/cameras/:cam_id",
std::bind(&admin_service::remove_camera, service, std::placeholders::_1));
在本例中,admin_service::remove_camera
是成员函数,service
是包含指向admin_service
对象的指针的shared_ptr
。如果有人请求此路由,则会调用admin_service::remove_camera
。
但是,服务器在执行结束时(当我们退出服务器时)会发生segfault。
我已经追踪到segfault的起源,它来自…的析构函数。。。std::function
。更准确地说,它发生在std::pair
的get
、post
、put
和del
中包含的std::function
之一被破坏的过程中。
我之所以这么说是因为,当我放入以下调试代码时:
struct rest_routes {
~rest_routes() {
std::cout << "BEGIN DTOR rest_routes" << std::endl;
std::cout << "BEGIN get" << std::endl;
get.first = nullptr;
std::cout << "END get" << std::endl;
std::cout << "BEGIN post" << std::endl;
post.first = nullptr;
std::cout << "END post" << std::endl;
std::cout << "BEGIN put" << std::endl;
put.first = nullptr;
std::cout << "END put" << std::endl;
std::cout << "BEGIN del" << std::endl;
del.first = nullptr;
std::cout << "END del" << std::endl;
std::cout << "END DTOR rest_routes" << std::endl;
}
std::regex regex;
std::vector<std::string> vars_name;
std::pair<std::function<http::response(http::request&)>, std::vector<std::string>> get;
std::pair<std::function<http::response(http::request&)>, std::vector<std::string>> post;
std::pair<std::function<http::response(http::request&)>, std::vector<std::string>> put;
std::pair<std::function<http::response(http::request&)>, std::vector<std::string>> del;
};
我得到了以下输出:
BEGIN DTOR rest_routes
BEGIN get
END get
BEGIN post
END post
BEGIN put
END put
BEGIN del
Segmentation Fault
我不知道std::函数如何在销毁或赋值过程中出错。。。
我最初认为,也许std::function
引用了std::shared_ptr service
,而不是按值,并多次删除了它包含的原始指针。但是,当我放入一些调试输出时,我可以看到shared_ptr
计数器在调用router.del
之后递增。
有人知道这个问题吗?
这看起来像是内存损坏问题。我会试试:
- 在
valgrind
下运行。如果可能的话,因为valgrind
模拟CPU,所以应用程序在单个虚拟线程下的运行速度要慢50倍。在CCD_ 21下,由竞争条件引起的错误可能不会表现出来 - 通过重新编译并使用
-fsanitize=address
命令行选项链接,使用gcc/clang地址清理程序。这个程序的工作原理令人惊讶,因为它的开销相对较低:一个装有Address Sanitizer的程序通常会比未装有地址的程序慢两倍,并且通常会多消耗20%的内存
相关文章:
- 什么时候调用组成单元对象的析构函数
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 什么时候调用析构函数
- 优先顺序:智能指针和类析构函数
- C++-明确何时以及如何调用析构函数
- 使用基类指针创建对象时,缺少派生类析构函数
- 在c++中使用向量时,如何调用构造函数和析构函数
- 重载运算符new[]的行为取决于析构函数
- 我需要知道编译器如何在cpp中使用析构函数
- 为什么在使用转换构造函数赋值后调用C++类的析构函数?
- 析构函数调用
- 通过引用传递-为什么要调用这个析构函数
- 对具有动态分配的内存和析构函数的类对象的引用
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 导致SegFault C++的析构函数
- 类析构函数 SEGFAULT
- std::函数析构函数中的Segfault
- 析构函数上的Segfault
- 在析构函数中释放内存时出现segfault