2010-04-30 111 views
4

我有一個緩衝區溢出,我絕對看不出來(在C中)。首先,大概只有10%的時間發生。每次從數據庫中提取的數據在執行之間似乎沒有太大的差異......至少在我看來不會發現任何可識別的模式。從Visual Studio確切的消息是這樣的:需要緩衝區溢出的幫助

緩衝區溢出發生在 hub.exe已損壞的 程序的內部狀態。按 中斷調試程序或繼續 終止程序。

有關更多詳細信息,請參閱幫助主題 '如何調試緩衝區溢出問題'。

如果我調試,我發現它在__report_gsfailure(),我敢肯定是從編譯器/ GS標誌,也意味着這是堆棧溢出,而不是堆破碎。我也可以看到它在離開時拋棄它的功能,但是我看不到會導致這種行爲的任何東西,這個功能也存在了很長時間(10年以上,雖然稍作修改)據我所知,這從來沒有發生過。

我會發布函數的代碼,但它很長,並引用了很多專有函數/變量/等。

我基本上只是尋找一些我應該尋找的想法,我沒有或者可能有些工具可以幫助。不幸的是,我發現幾乎所有的工具都只能幫助調試堆上的溢出,除非我錯了,這是堆棧中的事情。提前致謝。

回答

3

您可以嘗試在緩衝區的任一端放置一些局部變量,甚至將緩衝區本身放在稍稍擴展的緩衝區中,如果這些值不是您認爲應該是的那麼就觸發一個斷點。顯然,使用數據中不太可能的模式將是一個好主意。

+0

我加入了一些本地變量緩衝區,希望能夠獲得一些價值,並且這個問題在25次左右的嘗試中都沒有被重現(這比以前我所做的要多2-3倍)。這就像我添加的緩衝區填充了一切,足以讓任何事情都沒有崩潰。即使在我調試它們的時候,緩衝區在每次從函數返回之前都會保持我期望它們的確切值。 – Morinar 2010-04-30 21:42:00

+0

如果你只是擴展你的緩衝區,並且在它的末尾寫入一些已知的值,那該怎麼辦? – 2010-04-30 21:44:59

+0

你說如果我知道我正在覆蓋哪個緩衝區。如果不明確,我完全不知道。如果我知道哪個緩衝區超時,我只會設置一個硬件斷點並獲勝。 – Morinar 2010-04-30 22:26:26

3

雖然它不會幫助你在Windows中,Valgrind是迄今爲止檢測不良內存行爲的最佳工具。

如果您正在調試堆棧,您需要使用低級工具 - 在任何潛在的嫌疑人周圍放置一個金絲雀到堆棧框架(可能是一個填充類似0xA5的緩衝區)。在調試器中運行該程序,並查看哪些canaries不再是正確的大小幷包含正確的內容。你會吞噬一大堆這樣做,但它可以幫助你確切地發現正在發生的事情。

+0

是的,我以前用過它。雖然我們的服務器代碼確實在各種Unix(Solaris/HP/AIX)上運行,但它看起來並不像Valgrind那樣受支持,所以不幸的是,它並不能幫助我。 – Morinar 2010-04-30 18:48:47

0

將其包裝在異常處理程序中,並在發生時轉儲出有用的信息。

0

這個程序是否遞歸?如果是這樣,我在那裏檢查以確保您沒有無限遞歸錯誤。如果你不能手動看到它,有時你可以通過頻繁停頓和觀察堆棧來在調試器中捕獲它。

+0

沒有。沒有遞歸。 – Morinar 2010-04-30 21:09:01

1

我過去做過的一件事是幫助縮小這樣一個神祕錯誤,就是創建一個名爲checkpoint的全局可見性變量。在罪魁禍首裏面,我設置了checkpoint = 0;作爲第一行。然後,我在函數調用或內存操作之前和之後添加了++checkpoint;語句,我甚至可以遠程懷疑這些語句可能會導致超出內存的引用(加上其他代碼,這樣我至少每10次有一個檢查點線左右)。當程序崩潰時,checkpoint的值將縮小您需要關注的幾行代碼的範圍。這可能有點矯枉過正,我在嵌入式系統上做這種事情(不能使用像valgrind這樣的工具),但它應該仍然有用。

+0

好主意!接下來會嘗試。 – Morinar 2010-04-30 21:05:29

+0

我有一個幾乎所有其他的線......當它崩潰的時候它的價值就是它應該是的。 :- – Morinar 2010-04-30 21:40:21

+0

我不明白你的意思。如果在程序崩潰時檢查點是6(例如),那麼你的問題發生在第六個和第七個「++檢查點」語句之間。如果你能夠在崩潰後讀取這個值,它應該找出問題的根源。 – bta 2010-04-30 21:55:35