Visual Studio 2017 中的 C++ std::mutex lock() 访问冲突

Stu*_*7CB 5 c++ c++11 visual-studio-2017

当我尝试运行使用 VS2017 编译的可执行文件时,我Exception thrown at 0x00007FFF05BC1063 (msvcp140d.dll) in a.exe: 0xC0000005: Access violation reading location 0x0000000000000000.在启动后立即捕获 。

调试后,我发现当我试图锁定静态互斥锁 _coutMutex 时会发生这种情况。我该如何修复它,因为当我使用 mingw 进行编译时,它运行良好。这是我的代码的一部分:

游戏.hpp:

#include "Logger.hpp"

class Game
{
public:
    static Logger logger;
};
Run Code Online (Sandbox Code Playgroud)

游戏.cpp:

#include "Game.hpp"

Logger Game::logger{ "logs/client", Logger::LoggingLevels::Info, 
  Logger::LoggingLevels::Trace, 2, 100 };
Run Code Online (Sandbox Code Playgroud)

记录器.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;  
};
Run Code Online (Sandbox Code Playgroud)

记录器.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();
}
Run Code Online (Sandbox Code Playgroud)

主.cpp:

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

int main()
{
    Game game;
}
Run Code Online (Sandbox Code Playgroud)

gez*_*eza 5

正如 Richard Critten 所说,这一定是全局初始化顺序问题。

您有 2 个全局变量logger_coutMutex,它们位于不同的编译单元中。它们的初始化顺序没有定义。

Logger的构造函数运行时,_coutMutex尚未初始化,但_addToQueue想使用它。

你可以有三种解决方案:

  • 避免使用全局对象。或者避免使用做一些严重事情的全局构造函数(如果你_addToQueue从记录器构造函数中删除,它会起作用)。
  • 将这些全局变量按正确的顺序放入一个编译单元
  • 添加一个访问器函数_coutMutex,并在其中定义互斥锁(作为静态变量)。当心这个解决方案,因为它有它的缺点(速度、线程安全)