1

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

我有一个具有调解器的应用程序,例如:

class Mediator{
    ConfigMgr * mgr;
    ....
    Config getConfig(){
    return mgr->getConfig();
    };
};

ConfigMgr 已正确初始化,没有任何问题。除其他外,它包括一个 Config 蓝图,这是一个具有一些布尔值和 std::strings 的结构:

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::~Config() 该结构没有我编写的方法。

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

4

1 回答 1

1

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

  1. std::string 在复制时共享其 char* 缓冲区。
  2. std::string 不是为多线程设计的。

因此,您在不同的线程中遇到多个 std::strings 试图删除同一个缓冲区,他们认为由于引用计数变量没有正确更新而应该删除。

您可能必须更明确地了解您想要的字符串副本,并为 Config 对象定义一个复制构造函数。

于 2012-12-18T15:13:38.543 回答