1

今日のマルチスレッドの謎を解くには、手を貸してほしい。

メディエーターを持つアプリケーションがあります。たとえば、次のようにします。

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

ConfigMgr は適切に初期化されており、何の問題もありません。これは、いくつかのブール値と std::strings を持つ構造体である Config ブループリントで構成されています。

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 構造体は、参照ではなく、常にコピーによって渡されます。ConfigMgr::getConfig() の呼び出し以来、すべてのスレッドが独自の Config のコピーを持つべきだと思います。この構造はスレッドセーフである必要がありますが、明らかに何らかの競合状態があります。何かアドバイスはありますか?

4

1 に答える 1

1

私はこれに打たれました。覚えておくべき重要事項は次のとおりです。

  1. std::string は、コピー時に char* バッファーを共有します。
  2. std::string はマルチスレッド用に設計されていません。

したがって、同じバッファを削除しようとしている異なるスレッドで複数の std::strings にヒットしています。参照カウント変数が正しく更新されていないため、それらは削除する必要があると考えています。

おそらく、必要な文字列のコピーについてより明確にし、Config オブジェクトのコピー コンストラクターを定義する必要があります。

于 2012-12-18T15:13:38.543 に答える