c++ - 将 C++/Win32 控制台应用程序转换为 DLL 后崩溃

标签 c++ dll crash libxml2

我最近将一个高度线程化、非托管的 Win32 C++ 控制台应用程序 (MediaServer.exe) 转换为非托管的 Win32 DLL (MediaServer.dll)。我在一个单独的非托管 Win32 控制台应用程序中托管和调试此 DLL,所有内容都编译并运行,但大约一分钟后,我会随机崩溃,在一个毫无意义的地方,一个明显损坏的调用堆。这些崩溃发生在各种不同的地方,并且在某种程度上是随机的:但共同点是(显然已损坏的)调用堆栈总是在其某处具有各种 libxml2.dll 函数,例如,崩溃可能发生在看起来像像这样:

xmlDoc * document = xmlReadMemory(message.c_str(), message.length(), "noname.xml", NULL, 0);

或者像这样:

xmlBufferPtr buffer = xmlBufferCreate();

调用栈可能是这样的:

feeefeee()  
libxml2.dll!000eeec9()  
[Frames below may be incorrect and/or missing, no symbols loaded for libxml2.dll]   
libxml2.dll!00131714()  
libxml2.dll!001466b6()  
libxml2.dll!00146bf9()  
libxml2.dll!00146c3c()  
libxml2.dll!0018419e()  

或者如果你幸运的话,像这样:

ntdll.dll!_RtlpWaitOnCriticalSection@8()  + 0x99 bytes  
ntdll.dll!_RtlEnterCriticalSection@4()  - 0x15658 bytes 
libxml2.dll!1004dc6d()  
[Frames below may be incorrect and/or missing, no symbols loaded for libxml2.dll]   
libxml2.dll!10012034()  
libxml2.dll!1004b7f7()  
libxml2.dll!1003904c()  
libxml2.dll!100393a9()  
libxml2.dll!10024621()  
libxml2.dll!10036e8f()  
MediaServer.dll!Controller::parse(std::basic_string<char,std::char_traits<char>,std::allocator<char> > message)  Line 145 + 0x20 bytes  C++
MediaServer.dll!Controller::receiveCommands()  Line 90 + 0x25 bytes C++
MediaServer.dll!MediaServer::processCommands()  Line 88 + 0xb bytes C++
MediaServer.dll!MediaServer::processCommandsFunction(void * mediaServerInstance)  Line 450 + 0x8 bytes  C++
MediaServer.dll!CustomThread::callThreadFunction()  Line 79 + 0x11 bytes    C++
MediaServer.dll!threadFunctionCallback(void * threadInstance)  Line 10 + 0x8 bytes  C++
kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes    
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes   
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes    

崩溃本身通常会说类似“MediaServerConsole.exe 中 0x77cd2239 (ntdll.dll) 的未处理异常:0xC000005:访问冲突写入位置 0x00000014。”

不用说,当我将模块编译为控制台应用程序时,这并没有发生。

在将项目转换为 DLL 时,有什么我可能忽略的地方吗?这不是我以前做过的事情,所以如果我忽略了一些明显的事情,我一点也不会感到惊讶。感谢您的帮助。

最佳答案

我会说您正在 DLL_THREAD_ATTACH 而不是 DLL_PROCESS_ATTACH 中初始化内存。这种情况会导致您使用在执行线程之外的另一个线程中分配的指针或内存。

另一件事是检查 DLL 依赖项的加载情况。

让我解释一下。当您的 DLL 使用 loadlibrary 加载时,CRT 会进行全局内存分配。这是为了初始化所有全局变量,范围从 C 原始类型开始,默认情况下将它们初始化为零。然后它为结构/类分配内存,并在必要时调用它们的构造函数。

CRT 然后使用 DLL_PROCESS_ATTACH 调用您的 DLLMain 方法以告知您的进程加载的 DLL。对于该进程内的每个线程,CRT 然后使用 DLL_THREAD_ATTACH 调用您的 DLL。

您说过这些是空的,然后调用导出的 C 函数。虽然我可以看到你的 dll 陷入了关键部分。这告诉我,您的全局分配变量和您的线程在 Start() 中分配内存时发生了死锁情况。

我建议将您的初始化代码移动到 Process_Attached 中,这将确保您的所有内存都分配在主进程线程上,类似于应用程序作为单个可执行文件的工作方式。

关于c++ - 将 C++/Win32 控制台应用程序转换为 DLL 后崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6786106/

相关文章:

c++ - 让 DrawText 打断一个字符串

C++ dll使用dll中的方法

c# - 从 Powershell 调用的 DLL 使用相对于 Powershell 安装目录的路径。我怎样才能将它设置为其他东西?

c++ - 引用传递和值传递是否会导致C++程序时间复杂度的变化?

c++ - 从 QProcess 复制文件夹内容

arrays - swift 的 iOS。当我尝试改变按钮数组时程序崩溃

c++ - 模板化函数在返回值时崩溃

python - pythonw.exe 中发生未处理的 win32 异常 [11744]

c++ - lambda 函数抛出错误

c++ - 将 C 库与 C++ 链接