2011-05-06 157 views
2

此錯誤只有當我建立在「自由」(釋放),執行優化的WINDDK NMAKE編譯正在發生。我無法在「檢查」構建或VS編譯中重現此操作。奇怪的內存損壞

這裏是在我的代碼發生的僞代碼:

main() 
{ 
    //variable init and other code 
    fprintf(log, "pre nullValue: %lu\n", NULL); //printf added for debugging 
    otherFunc(); 
    funcWithError(str1, str2, NULL); 
    fprintf(log, "post nullValue: %lu\n", NULL); 
    fprintf(log, "post2 nullValue: %lu, %lu, %lu\n", NULL, 0, NULL); 
} 

BOOL otherFunc() 
{ 
    //variable init and other code 
    callToDll(); 
    //...doing stuff 
    libusb_usb_open(var1); //If I remove this line there is no problem!! 
    //...doing more stuff 
} 

BOOL funcWithError(char* s1, char* s2, FUNC_PTR fp) 
{ 
    fprintf(log, "inFunc nullValue: %lu, %lu\n", NULL, fp); 
    if(fp != NULL) 
     return FALSE;  //This line is being executed erroneously!! 
} 

輸出日誌:
預NullValue屬性:0
inFunc NullValue屬性:0,251208
後NullValue屬性:251208
post2 nullValue:251208,251208,251208
注意:重新發生的號碼(251208)是不同數量的每次程序運行

只需改變一個線修復/導致它的時間。這是libusb usb_open電話。

  1. 最終我的問題是要弄清楚如何解決這個問題(我無法避免調用)
  2. 但在堆疊/內存管理水平只是如何它甚至有可能有NULL不爲零並將文字值'0'打印爲非零?

讓我瞭解其他信息,可以幫助...

+1

也許東西是錯誤的參數傳遞約定libusb_usb_open,這導致一些堆棧損壞。這是64位的應用程序?也許你應該使用%llu而不是%lu。最好的辦法,找出哪些是錯誤的將是調試的彙編代碼這一部分,並檢查怎麼回事。 – Zuljin 2011-05-06 23:34:36

+0

是啊,我試圖挽救翻翻組裝,所以以爲我會發布。它在x86機器上編譯x86,所以不是64位。所以%llu什麼都不做。 – Sogger 2011-05-06 23:56:18

回答

3

並不是一個完全灌籃高手。但這個堆棧很可能不平衡。在調試器(是的,你可以調試發佈版本),之前和呼叫後檢查ESP寄存器的值。它應該是一樣的。如果函數的調用約定是錯誤的,則不會。像__stdcall vs __cdecl。

這可以隱藏自身以及當您建立與NMAKE.EXE程序,很容易忘了打開的調試版本/ RTC的選項,以便棧檢查的代碼被髮射。並且ESP寄存器傾向於在函數返回時自行恢復。直到你建立地方職能得到內聯和EBP的使用進行了優化掉這樣ESP不會恢復自身的再發布版本。

+0

我編寫並沒有任何錯誤運行該代碼/ RTC1 – Sogger 2011-05-09 17:54:41

+0

是,現在更好嗎? :) – Sogger 2011-05-11 17:17:43

0

更新:所以,我終於得到windbg闖入DLL並檢查一些事情。那是,我原本懷疑和漢斯指出,造成不匹配的調用約定堆棧的腐敗。

只在發佈版本中可見的是,編譯器優化了0/Null值,使用ebx寄存器值而不是傳遞0.在OtherFunc()中,優化使用ebx存儲其他幾個值,然後對Usb_Open()的調用破壞了堆棧,然後當OtherFunc()試圖彈出堆棧以恢復原始的ebx值時,它恢復了垃圾而不是「0」。所以,在main()中,每個對NULL的優化引用都使用這個垃圾值。

注意:其他dll調用不會破壞堆棧的原因是因爲它們沒有參數。

所以在最後的答案:

  1. 呼叫libusb的使用權約定(libusb的使用__cdecl調用約定,NMAKE默認使用__stdcall)
  2. 即使NULL和「0」是硬編碼的源代碼,編譯器可以優化使用的寄存器,而不是傳遞值和寄存器都受到從壞代碼腐敗。
+0

嘿,感謝您的回答大關! – 2011-05-10 23:58:29