2011-07-22 95 views
1

我最近將高度線程化的非託管Win32 C++控制檯應用程序(MediaServer.exe)轉換爲非託管Win32 DLL(MediaServer.dll)。我在一個單獨的非託管Win32控制檯應用程序中託管和調試此DLL,並且所有內容都會編譯並運行,但一分鐘左右後,我會隨機發生崩潰,在一個毫無意義的地方發生,並顯示一個顯然已損壞的調用疊加。這些崩潰發生在各種不同的地方,並且在某些隨機時間發生:但通用性是(顯然已損壞的)調用堆棧總是在其上某處存在各種libxml2.dll函數,例如,崩潰可能在看起來像一條線像這樣:將C++/Win32控制檯應用程序轉換爲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() 

或者,如果你是幸運的,就像這樣:

[email protected]() + 0x99 bytes 
[email protected]() - 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++ 
[email protected]@12() + 0x12 bytes  
[email protected]() + 0x27 bytes 
[email protected]() + 0x1b bytes  

崩潰本身通常會這樣說: 「在0x77cd2239(ntdll.dll中)在MediaServerConsole.exe未處理的異常:0xC000005:訪問衝突寫入位置0x00000014。」

不用說,當我編譯模塊作爲控制檯應用程序時,沒有發生這種情況。

將項目轉換爲DLL時,可能忽略了什麼?這不是我以前做過的事情,所以如果有什麼明顯的我忽略了,我不會感到驚訝。任何幫助表示讚賞。

+0

您是否嘗試過在運行任何[本主題]中的建議程序(http://stackoverflow.com/questions/413477/is-there-a-good-valgrind-substitute-for-windows)? Purify,Insure ++等可以幫助您追蹤程序中的細微錯誤。 –

+0

還沒有,但我現在正在下載Visual Leak Detector,看它是否可以確定任何事物。 (推測它不在Purify或Insure ++的同一級別,但它是免費的......) –

+0

什麼導致了崩潰?訪問違規?我假設是,因爲釋放的堆標有0xFEEFEEE。這聽起來像你的堆棧溢出或你的堆已損壞。此外,您可以檢查DLL鏈接的CRT(靜態/動態,調試/發佈) –

回答

1

我會說你正在初始化DLL_THREAD_ATTACH內存而不是DLL_PROCESS_ATTACH。這種情況會導致你使用已經在另一個線程中分配的指針或內存,而不是正在執行的線程。

另一件事是檢查你的加載你的DLL的依賴關係。

讓我解釋一下。當您的DLL使用loadlibrary加載時,CRT執行全局內存分配。這是爲了初始化所有全局變量,範圍從C初始類型,默認情況下它們初始化爲零。然後它爲struct/classes分配內存,並在必要時調用其構造函數。

然後,CRT使用DLL_PROCESS_ATTACH調用您的DLLMain方法來告訴您的進程已加載的DLL。對於該進程中的每個線程,CRT會使用DLL_THREAD_ATTACH調用您的DLL。

你說過這些空了,然後你打電話給你導出的C函數。雖然我可以看到你會被抓到關鍵部分。這告訴我,您的全局分配變量和您的線程在Start()中分配內存時發生死鎖情況。

我建議您在Process_Attached內移動您的初始化代碼,這將確保您的所有內存都分配在主進程線程上,類似於應用程序如何作爲單個可執行文件運行。

+0

這是一件好事,但我的DllMain(正如MS顯然推薦的那樣)是一個空的存根。我目前只在一個Start()函數中分配內存,聲明爲:extern「C」__declspec(dllexport)int Start(){/ * Stuff * /} –

+0

是的,但CRT在不同的線程上分配全局內存。這就是我所掌握的。看起來當兩個線程試圖訪問CriticalSection時,你會遇到死鎖。 – Chad

+0

很可能我在這裏錯過了一些東西,然後:-)。如果我沒有初始化DllMain中的任何東西,我如何確保我在Start()中初始化的內容在正確的線程上正確初始化? –

0

我會留下對方的回答是「接受」的答案,但它可能有助於人們瞭解這個問題的一個關鍵部分是事實,我是錯誤的線程上初始化的libxml2。具體來說,在進行任何調用之前,您需要在主線程上調用xmlInitParser()。對我來說,這意味着:

MediaServer::MediaServer() : mProvidePolicyThread (0), 
         mProcessCommandsThread(0), 
         mAcceptMemberThread (0) 
{ 
    xmlInitParser(); 
} 

,同樣,你需要調用xmlCleanupParser()當您退出:

MediaServer::~MediaServer() 
{ 
    xmlCleanupParser(); 
} 

這是這裏的所有記載:http://xmlsoft.org/threads.html

相關問題