生活随笔
收集整理的這篇文章主要介紹了
堆栈错误
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
寫此文的目的是為了說明: -> 并非所有的異常都能夠做到“不彈框優雅地退出”,堆棧錯誤因為可能影響安全,所以在異常處理時被加以了限制; -> 堆、棧的頭部、尾部被破壞,共有4種情況,現象其實是不一樣的,應當加以區分。知道這一點應該能夠為排查錯誤帶來一些幫助。
先來一個“普通的”異常:除零異常
#include <string.h>
#include <stdio.h>
#include <excpt.h>
#include <stdlib.h> int main()
{
int a =
1 ;
int b =
0 ;
int ab = a / b;
return 0 ;
}
========== 2. 除零異常是可以被正常捕獲并處理的
#include <string.h>
#include <stdio.h>
#include <excpt.h>
#include <stdlib.h> int MyMain()
{
int a =
1 ;
int b =
0 ;
printf (
"-----start-----\n" );
int ab = a / b;
printf (
"-----finish-----\n" );
return 0 ;
}
int main()
{__try{MyMain();}__except (EXCEPTION_EXECUTE_HANDLER){
printf (
"!!!!! Quit with Exception In MyMain !!!!!\n" );
exit (-
1 );}
}
========== 3.堆頭部被破壞
#include <string.h>
#include <stdio.h>
#include <excpt.h>
#include <stdlib.h> int MyMain()
{
char *c =
new char [
5 ];c[
0 ] =
'a' ;c[
1 ] =
'b' ;c[
2 ] =
'c' ;c[
3 ] =
'd' ;c[
4 ] =
'\0' ;c[-
1 ] =
'z' ;
printf (
"c=%s\n" , c);
printf (
"-----start-----\n" );
delete c;
printf (
"-----finish-----\n" );
return 0 ;
}
int main()
{__try{MyMain();}__except (EXCEPTION_EXECUTE_HANDLER){
printf (
"!!!!! Quit with Exception In MyMain !!!!!\n" );
exit (-
1 );}
}
注意以下幾點: (1) 紅色框部分:wrote to memory before start of heap buffer。 (2) 堆錯誤即使加了異常處理語句,也會彈出錯誤框。 (3) 當堆頭部被修改后,仍可以正常讀取堆內容。 (4) 在釋放資源時才會發生異常。 (5) 如果點擊“中止”,則程序隨即停止;如果點擊“重試”,則進入異常處理程序(說明其實還是能捕獲到的,只是無法直接隱藏錯誤窗口);如果點擊忽略,則程序繼續進行。下圖依次顯示了點擊“中止”“重試”“忽略”的情況。
========== 4. 堆尾部被破壞
#include <string.h>
#include <stdio.h>
#include <excpt.h>
#include <stdlib.h> int MyMain()
{
char *c =
new char [
5 ];c[
0 ] =
'a' ;c[
1 ] =
'b' ;c[
2 ] =
'c' ;c[
3 ] =
'd' ;c[
4 ] =
'\0' ;c[
5 ] =
'z' ;
printf (
"c=%s\n" , c);
printf (
"-----start-----\n" );
delete c;
printf (
"-----finish-----\n" );
return 0 ;
}
int main()
{__try{MyMain();}__except (EXCEPTION_EXECUTE_HANDLER){
printf (
"!!!!! Quit with Exception In MyMain !!!!!\n" );
exit (-
1 );}
}
注意以下幾點: (1) 紅色框部分:wrote to memory after end of heap buffer。 其他同堆頭部被破壞的信息。
========== 5. 棧頭部被破壞
#include <string.h>
#include <stdio.h>
#include <excpt.h>
#include <stdlib.h> int MyMain()
{
char c[
5 ];
memset (c,
0 ,
sizeof (c));c[
0 ] =
'a' ;c[
1 ] =
'b' ;c[
2 ] =
'c' ;c[
3 ] =
'd' ;c[
4 ] =
'\0' ;c[-
1 ] =
'z' ;
printf (
"c=%s\n" , c);
printf (
"-----start-----\n" );
delete c;
printf (
"-----finish-----\n" );
return 0 ;
}
int main()
{__try{MyMain();}__except (EXCEPTION_EXECUTE_HANDLER){
printf (
"!!!!! Quit with Exception In MyMain !!!!!\n" );
exit (-
1 );}
}
注意以下幾點: (1) 棧錯誤即使加了異常處理語句,也會彈出錯誤框。 (2) 當棧頭部被修改后,仍可以正常讀取堆內容。 (3) 在釋放資源時才會發生異常。 (4) 如果點擊“中止”,則程序隨即停止;如果點擊“重試”,則進入異常處理程序(說明其實還是能捕獲到的,只是無法直接隱藏錯誤窗口);如果點擊忽略,則程序繼續進行,仍會繼續拋出異常,再次點擊忽略,再次拋出異常,第三次點擊繼續,程序進入異常處理。下圖依次顯示了點擊“中止”“重試”“忽略”的情況。
========== 6.棧尾部被破壞
#include <string.h>
#include <stdio.h>
#include <excpt.h>
#include <stdlib.h> int MyMain()
{
char c[
5 ];
memset (c,
0 ,
sizeof (c));c[
0 ] =
'a' ;c[
1 ] =
'b' ;c[
2 ] =
'c' ;c[
3 ] =
'd' ;c[
4 ] =
'\0' ;c[
5 ] =
'z' ;
printf (
"c=%s\n" , c);
printf (
"-----start-----\n" );
delete c;
printf (
"-----finish-----\n" );
return 0 ;
}
int main()
{__try{MyMain();}__except (EXCEPTION_EXECUTE_HANDLER){
printf (
"!!!!! Quit with Exception In MyMain !!!!!\n" );
exit (-
1 );}
}
注意以下幾點: (1) 點擊兩次忽略后,程序結束。與棧頭部錯誤有所區別。(可能因為頭部指針沒有問題,所以沒有報“_CrtIsValidHeapPointer(pUserData)”異常)
關于異常無法捕獲的補充材料請參考: Error的博文 Error的博文
總結
以上是生活随笔 為你收集整理的堆栈错误 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。