我最近将一个高度线程化的非托管Win32 C++ console应用程序(MediaServer.exe)转换为一个非托管Win32动态链接库(MediaServer.dll)。我在一个单独的非托管Win32控制台应用程序中托管和调试这个动态链接库,一切都会编译并运行,但大约一分钟后,我会在一个没有任何意义的地方随机崩溃,而且调用堆栈明显已损坏。这些崩溃发生在各种不同的地方,在一些随机的时间:但共性是(明显损坏的)调用堆栈总是在它的某个地方有各种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: 0xC000005: Access violation writing location 0x00000014中的0x77cd2239 (ntdll.dll)未处理异常”。
不用说,当我将该模块编译为控制台应用程序时,并没有发生这种情况。
在将项目转换为DLL时,有没有什么我可能忽略的地方?这不是我以前做过的事情,所以如果有什么明显的事情我忽略了,我一点也不会感到惊讶。任何帮助都是非常感谢的。
发布于 2011-07-22 14:38:20
我会说你是在DLL_THREAD_ATTACH而不是DLL_PROCESS_ATTACH中初始化内存。这种情况会导致您使用已在另一个线程而不是执行线程中分配的指针或内存。
另一件事是检查DLL的依赖项的加载情况。
让我解释一下。当使用loadlibrary加载DLL时,CRT执行全局内存分配。这是为了初始化所有的全局变量,范围从将它们初始化为零的C原语类型。然后,它为struct/classes分配内存,如果需要,还会调用它们的构造函数。
然后,CRT使用DLL_PROCESS_ATTACH调用您的DLLMain方法,以告知您的进程已加载的DLL。对于该进程中的每个线程,CRT然后使用DLL_THREAD_ATTACH调用您的DLL。
您已经说过这些都是空的,然后调用导出的C函数。虽然我可以看到你的dll在一个临界区被抓住了。这告诉我,您的全局分配变量和线程在Start()中分配内存时发生了死锁情况。
我建议在Process_Attached中移动初始化代码,这将确保所有内存都分配在主进程线程上,类似于应用程序作为单个可执行文件的工作方式。
发布于 2011-07-26 21:13:20
我将保留另一个答案作为“接受的”答案,但让人们知道问题的一个关键部分是我在错误的线程上初始化libxml2的事实可能会有所帮助。具体地说,在进行任何调用之前,您需要在主线程上调用xmlInitParser()。对我来说,这意味着:
MediaServer::MediaServer() : mProvidePolicyThread (0),
mProcessCommandsThread(0),
mAcceptMemberThread (0)
{
xmlInitParser();
}同样,您需要在退出时调用xmlCleanupParser():
MediaServer::~MediaServer()
{
xmlCleanupParser();
}所有这些都记录在这里:http://xmlsoft.org/threads.html
https://stackoverflow.com/questions/6786106
复制相似问题