2017-07-09 80 views
1

VS2017を使用してコンパイルされた実行可能ファイルを実行しようとすると、起動直後に Exception thrown at 0x00007FFF05BC1063 (msvcp140d.dll) in a.exe: 0xC0000005: Access violation reading location 0x0000000000000000.がキャッチされます。Visual StudioのC++ std :: mutex lock()アクセス違反2017

デバッグ後、私は静的mutex _coutMutexをロックしようとしているときに起こることを理解しました。 mingwを使ってコンパイルしたときにうまくいきましたので、どうすれば修正できますか?ここに私のコードの一部です:

Game.hpp:

#include "Logger.hpp" 

class Game 
{ 
public: 
    static Logger logger; 
}; 

Game.cpp:

#include "Game.hpp" 

Logger Game::logger{ "logs/client", Logger::LoggingLevels::Info, 
    Logger::LoggingLevels::Trace, 2, 100 }; 

Logger.hpp:

#include <mutex> 

class Logger 
{ 
public: 
    Logger(std::string path, short consoleLoggingLevel, short 
     fileLoggingLevel, uint32_t count, size_t maxSize); 

    enum LoggingLevels : short 
    { 
     Off = 0, 
     Fatal = 1, 
     Error = 2, 
     Warn = 3, 
     Info = 4, 
     Debug = 5, 
     Trace = 6 
    }; 

void _addToQueue(std::string data); 
private: 
    static std::mutex _coutMutex; 
}; 

Logger.cpp :

std::mutex Logger::_coutMutex; 

Logger::Logger(std::string path, short consoleLoggingLevel, 
    short fileLoggingLevel, uint32_t count, size_t maxSize) 
{ 
    _addToQueue("dd/mm/yyyy hh:mm:ss.sss\n"); 
} 

void Logger::_addToQueue(std::string data) 
{ 
    _coutMutex.lock(); 
    std::cout << data; 
    _coutMutex.unlock(); 
} 

main.cppに:

#include "Logger.hpp" 
#include "Game.hpp" 

int main() 
{ 
    Game game; 
} 
+0

グローバルスタンダードから 'std :: cout'になる可能性があります - これがグローバル初期化の順序問題であるかどうかは分かりませんが、この解決策には注意してください。 –

+0

これはあなたの問題には対処していませんが、 'cout' /' stdout'への「ロギング」は、特に長寿命のプロセスではひどいことに気づいていますか?ログファイルがそのディスクをいっぱいにするとどうなりますか?それが起こったときに回復する唯一の信頼できる方法について 'cout'(または' cerr'や 'stderr'など)にロギングしていると、プロセスが終了します。本当に堅牢なロギングAPIは、ファイルにロギングし、必要に応じてログファイルを別のファイルにロールバックすることができます(例えば、 'SIGHUP'など) –

答えて

1

リチャードCrittenが示唆するように、これはグローバルな初期化順序の問題でなければなりません。

2つのグローバル変数logger_coutMutexがあります。これらは異なるコンパイル単位です。それらが初期化される順序は定義されていません。

Loggerのコンストラクタを実行すると、_coutMutexはまだ初期化されていませんが、_addToQueueは使用します。

次の3つの解決策かもしれない:

  • はグローバルオブジェクトを使用しないでください。また、重大な何かをするグローバルコンストラクタを使わないでください(loggerコンストラクタから_addToQueueを削除するとうまくいきます)。
  • これらのグローバル変数を正しい順序で1つのコンパイル単位に配置します。
  • _coutMutexのアクセサー関数を追加し、内部にmutexを静的変数として定義します。
関連する問題