版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/Fish_55_66/article/details/50601289
最近在DLL中使用日志库EasyLogging++记录日志时,因为涉及到多线程,所以我定义了宏了ELPP_THREAD_SAFE来启用多线程安全,但是当我以静态方式调用DLL时,我发现应用程序启动后就没反应了,甚至连 main() 之类的入口函数都进不去。一开始根本不知道什么原因导致了这种情况,这个问题困扰了我近两天的时间,通过慢慢分析,终于发现了原来是因为ELPP_THREAD_SAFE宏定义导致日志库EasyLogging++在初始化时出现了死锁的现象。下面的代码简单展示了这样一个会死锁的现象:
DLL头文件代码:
// testDLL.h
#ifndef TEST_LOG_H_
#define TEST_LOG_H_
#define ELPP_AS_DLL
#if defined(EL_EXPORTS)
# define ELPP_EXPORT_SYMBOLS
#endif
#define ELPP_THREAD_SAFE
#include "easyloggingpp/easylogging++.h"
#endif
/// 测试函数
extern "C" __declspec(dllexport) void Test();
DLL源文件代码:
// testDLL.cpp
#include "testDLL.h"
INITIALIZE_EASYLOGGINGPP
void Test()
{
LOG(ERROR) << "TEST";
}
静态调用该DLL的代码:
// main.cpp
#include <iostream>
#include "../testDLL.h"
#pragma comment(lib, "testDLL.lib")
int main()
{
std::cout << "TEST\n";
Test();
}
在Windos 7系统下,用Visual Studio 2013编译并运行上述代码,你会看不到任何输出。我们知道,在进入main函数之前,应用程序会先加载DLL,而在DLL的源文件中调用宏定义 INITIALIZE_EASYLOGGINGPP 进行日志库初始化,使用std::mutex 类进行多线程安全锁定时就出现了死锁,从而导致应用程序根本无法进入到main函数。这里给出几个链接,同样是因为在DLL中使用了std::mutex 从而导致了死锁的现象:
那么我们在Windows 7系统或者更低版本的系统中,如何使用日志库EasyLogging++记录DLL中的日志呢?仔细看EasyLogging++线程安全部分的代码,我们可以用一个很简单的方法来解决这个问题,就是使用 CRITICAL_SECTION 来代替 std::mutex 类。具体的代码修改如下:
在上图中,红框圈起来的代码就是改动新增的代码,通过在取消ELPP_USE_STD_THREADING宏定义,就可以解决 std::mutex 死锁的现象。
说明:只有应用程序以静态方式调用DLL时才会出现死锁的现象,如果以动态方式调用DLL是不会出现死锁的。