Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;多线程应用程序中结构析构函数中的SIGABRT_C++_Linux_Multithreading_Posix_Sigabrt - Fatal编程技术网

C++ c++;多线程应用程序中结构析构函数中的SIGABRT

C++ c++;多线程应用程序中结构析构函数中的SIGABRT,c++,linux,multithreading,posix,sigabrt,C++,Linux,Multithreading,Posix,Sigabrt,我需要帮助解决今天的多线程之谜 我有一个有调解人的应用程序,比如: class Mediator{ ConfigMgr * mgr; .... Config getConfig(){ return mgr->getConfig(); }; }; ConfigMgr已正确初始化,没有任何问题。除其他外,它还包括一个配置蓝图,这是一个包含一些布尔值和std::字符串的结构: struct Config{ std::string param1;

我需要帮助解决今天的多线程之谜

我有一个有调解人的应用程序,比如:

class Mediator{
    ConfigMgr * mgr;
    ....
    Config getConfig(){
    return mgr->getConfig();
    };
};
ConfigMgr已正确初始化,没有任何问题。除其他外,它还包括一个配置蓝图,这是一个包含一些布尔值和std::字符串的结构:

struct Config{
    std::string param1;
    std::string param2;
    ....
}

class ConfigMgr {
    Config blueprint;

    Config getConfig(){
        Lock l(mtx); //wrapper on POSIX mutex and lock, works as expected
        refreshConfig(); // some stuff that might alter Config blueprint
        return config;
    }

}
最后,我有多个工作线程,有时可能需要调用它们
mediator->getConfig().param1

问题是我的应用程序不时会因SIGABRT崩溃。根据我所能确定的,它在配置的析构函数中双重删除字符串时崩溃:
Config::~Config()
结构没有我编写的方法


我找不到根本原因。我的配置结构总是通过副本传递,而不是引用。我认为自从调用ConfigMgr::getConfig()以来,每个线程都应该有自己的配置副本。这种构造应该是线程安全的,但显然存在某种竞争条件。你们有什么建议吗?

我被这个打击了。要记住的重要事项是:

  • string在复制时共享其char*缓冲区
  • string不是为多线程设计的
  • 因此,您正在尝试删除同一缓冲区的不同线程中点击多个std::string,他们认为应该删除该缓冲区,因为引用计数变量未正确更新


    您可能需要更明确地说明所需的字符串副本,并为Config对象定义一个副本构造函数。

    我遇到了这个问题。要记住的重要事项是:

  • string在复制时共享其char*缓冲区
  • string不是为多线程设计的
  • 因此,您正在尝试删除同一缓冲区的不同线程中点击多个std::string,他们认为应该删除该缓冲区,因为引用计数变量未正确更新


    您可能需要更明确地说明所需的字符串副本,并为配置对象定义一个复制构造函数。

    是否有可能两次删除拥有
    Config
    对象的
    ConfigMgr
    实例?是否
    getConfig
    是从工作线程到
    ConfigMgr
    的唯一API?@BenVoigt:ConfigMgr未被删除。我的意思是,它只在程序关闭时被删除,不能在运行时被删除。icepack:实际上,configMgr还有三个线程可能调用的方法,所有都使用锁/互斥锁进行保护,并且都返回唯一的字符串或int。我跳过了这一点,因为我认为这与此无关。是否有可能拥有
    Config
    对象的
    ConfigMgr
    实例被删除了两次?是否
    getConfig
    是从您的工作线程到
    ConfigMgr
    的唯一API?@BenVoigt:ConfigMgr不是删除。我的意思是,它只在程序关闭时被删除,不能在运行时被删除。icepack:实际上,configMgr还有三个线程可能调用的方法,所有方法都使用锁/互斥锁进行保护,并且所有方法都返回唯一字符串或int。我跳过了这一点,因为我认为这与此无关。你的意思是,如果你有一个全局字符串对象,它是在启动期间分配的(而进程是单线程的)后来多个线程复制了它(但没有对共享字符串实例进行任何更改),那么这不安全吗?这太可怕了。Beovigt我用ValGRing和String拷贝验证了第一点,第二点是显而易见的,因为C++中有线程的历史。(这意味着某些实现可能是线程安全的,但不是必需的)。@BenVoigt当字符串同时复制到两个线程中时,它们可能不会充分增加引用计数,那么缓冲区可能会提前释放(允许引用释放内存),类似地,如果多个线程同时释放字符串副本,他们可能会尝试释放缓冲区-AFAIK。是的,我查看了标准,它严重地未指定是否允许非变异函数修改共享内存位置。在当前的非规范状态下,即使线程库也不一定可以从多个线程中使用。这肯定是我希望他们将来能解决的问题。谢谢你的回答,这帮了大忙。我通过创建struct Config的复制构造函数解决了这个问题,我使用互斥锁对其进行保护,并确保重新创建缓冲区,而不是共享缓冲区。您的意思是,如果您有一个全局字符串对象,它是在启动期间分配的(进程是单线程的),然后多个线程复制它(但没有什么改变共享字符串实例),这是不安全的。这是可怕的。@ Beoviigt我已经验证了第一点,使用ValgRing和字符串拷贝,第二个是显而易见的,在C++中有线程的历史。(这意味着一些实现可能是线程安全的,但它不是必需的)。.@BenVoigt当字符串同时在两个线程中复制时,它们可能不会充分增加引用计数,那么缓冲区可能会提前释放(允许引用释放内存),类似地,如果多个线程同时释放字符串副本,它们可能会多次尝试释放缓冲区-AFAIK。是的,我查看了标准,对于是否允许非变异函数修改共享内存位置的规定严重不足。在非规范的当前状态下,甚至线程库也不允许必须可以从多个线程中使用。这肯定是我希望他们将来能够解决的问题。感谢你的回答,这帮了我很大的忙。我通过创建struct Config的复制构造函数解决了这个问题,我使用互斥锁对其进行了保护,并确保缓冲区是重新创建的,而不是共享的。