2013-01-18 24 views
2

非常簡單地說,如果一個C++程序執行以下函數(比如在Windows 7上,使用任何VS版本進行編譯),然後崩潰,然後您使用WER附加調試器,或者WER生成崩潰轉儲並稍後分析崩潰轉儲。是否可以直接識別覆蓋整個堆棧的錯誤代碼?

是從垃圾堆裏的信息有可能,以直接推斷,這個功能被執行,也就是找到屬於那個執行它,這個函數在執行線程痕跡。

或者當我損壞整個堆棧時,所有的執行軌跡都消失了嗎?

void bye_bye_stack() { 
    int local = 42; 
    int* stackaddr = &local; 
    while(time(NULL) != NULL) { // prevent optimizations via call to time() 
    ++stackaddr; // stack grows towards smaller addresses, so increasing the pointer will point to info we already put on the stack 
    *stackaddr = local; // destroy stack content 
    // program will (likely) crash here once we reach a read-only page 
    } 
} 
+0

使用valgrind? (填充物) – 2013-01-18 14:12:35

+1

不,這是極端的痛苦。 EIP和EBP是垃圾,ESP指向爆炸的堆棧幀,許多可能已經丟失。你所能做的就是回去嘗試找到一個沒有踩踏的返回地址。這仍然只給你一小部分調用堆棧。接下來您考慮使用安全的CRT功能。 –

回答

1

一般情況下,通過按照您所做的方式銷燬堆棧,您將銷燬'callstack',這意味着有關先前調用的例程的信息將會消失。但是,如果您在此例程中觸發了訪問衝突/分段錯誤,則將存儲發生此事件的指令指針,指向此例程。

但是,如果堆棧損壞,並且您從此例程返回,那麼即使不是不可能,也很難找出發生的事情。

如果你想弄清楚發生了什麼,我建議使用一個調試工具來找出堆棧被「砸碎」的位置。如果你的意圖是破壞執行的證據,確保你從這個例程中'跳'或'返回',而不會觸發異常。

+0

問題在於,在此函數內引發了訪問衝突*。但是,Windows x86代碼將開始嘗試查找Win32 SEH異常處理程序,然後這會消除初始錯誤。通過附加調試器並打破一次機會異常,可以找到該函數。但是,一旦SEH異常處理機制開始執行(即,當不突破第一次機會異常時),似乎所有的痕跡都消失了。 –

1

這不是直接回復你的問題。

但是,當我遇到堆棧被覆蓋時,我用來啓動在開始覆蓋堆棧時立即斷言的實用程序gflags。

Gflags is provided by Microsoft

-1

這真的取決於。崩潰轉儲中提供的後端直接依賴存儲在堆棧中的信息。這通常意味着當您懷疑堆棧損壞時,您不能相信回溯。

由您提供的功能很可能會損壞整個堆棧,然後在超出段限制或達到進程不可用的內存時導致異常。此時,堆棧中沒有任何東西可以指示嫌疑犯。