std::函数析构函数中的Segfault 我目前正在维护C++开发的C++ REST服务器。它提供了一些特性,如中间件和路由

std::函数析构函数中的Segfault 我目前正在维护C++开发的C++ REST服务器。它提供了一些特性,如中间件和路由,c++,c++11,segmentation-fault,std-function,stdbind,C++,C++11,Segmentation Fault,Std Function,Stdbind,路由存储在router类的内部结构中: //! 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:

路由存储在router类的内部结构中:

//! 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;
    };
};
在此示例中,
admin\u service::remove\u camera
是一个成员函数,
service
是一个
shared\u ptr
包含指向
admin\u service
对象的指针。如果有人请求此路由,将调用
admin\u service::remove\u camera

但是,服务器会在执行结束时(当我们退出服务器时)发生故障

我已经追踪到了断层的起源,它来自于<代码>标准::函数。更准确地说,它发生在销毁
std::pair
s
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;
};
我无法理解std::函数如何在销毁或赋值过程中出错

我首先想到的可能是,
std::function
引用了
std::shared_ptr服务
,而不是按值引用,并多次删除了它包含的原始指针。但当我输入一些调试输出时,我可以看到调用
router.del
后,
shared_ptr
计数器增加


有人知道这个问题吗?

看起来像是内存损坏问题。我会尝试:

  • 在下面运行它。如果可能的话,因为
    valgrind
    模拟CPU,因此应用程序在单个虚拟线程下的运行速度要慢50倍左右。由竞争条件引起的错误可能不会在
    valgrind
    下出现
  • 通过重新编译并使用
    -fsanize=address
    命令行选项链接,使用gcc/clang。这是一个令人惊讶的工作原理,因为它相对较低:一个装有地址消除器的程序的运行速度通常是未装有地址消除器的程序的两倍,并且通常会多消耗20%的内存

我无法理解std::函数如何在销毁或分配过程中隔离故障
更进一步,在析构函数中隔离导致隔离故障的代码行或步骤。这就是我在第二段代码中所做的:我刚刚更改了
std::function
del.first=nullptr
)中包含的值。它会在分配过程中导致SEGFULT。此赋值运算符调用可能有一些类似于析构函数的操作(如销毁内部属性)。但我现在已经知道了如何进一步,除了打开标准库源代码之外。尝试将原始指针指向
std::function
,而不是
shared\u ptr
。像这样
。。。std::bind(&admin\u service::remove\u摄像机,service.get(),std::占位符::\u 1)
结果相同。我还尝试直接传递一个对象(
std::bind(&admin\u service::remove\u-camera,*(service.get()),std::placeholders::\u 1)
),但segfault仍在同一位置发生。显然,当我删除routes配置时,程序会正确退出。@SimonNinon
del
实例仍然有效吗?这是我能看到指针赋值崩溃的唯一方法,也就是说,持有指针的底层对象是无效的。
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