生活随笔
收集整理的這篇文章主要介紹了
堆栈错误
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
寫(xiě)此文的目的是為了說(shuō)明: -> 并非所有的異常都能夠做到“不彈框優(yōu)雅地退出”,堆棧錯(cuò)誤因?yàn)榭赡苡绊懓踩?#xff0c;所以在異常處理時(shí)被加以了限制; -> 堆、棧的頭部、尾部被破壞,共有4種情況,現(xiàn)象其實(shí)是不一樣的,應(yīng)當(dāng)加以區(qū)分。知道這一點(diǎn)應(yīng)該能夠?yàn)榕挪殄e(cuò)誤帶來(lái)一些幫助。
先來(lái)一個(gè)“普通的”異常:除零異常
#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 );}
}
注意以下幾點(diǎn): (1) 紅色框部分:wrote to memory before start of heap buffer。 (2) 堆錯(cuò)誤即使加了異常處理語(yǔ)句,也會(huì)彈出錯(cuò)誤框。 (3) 當(dāng)堆頭部被修改后,仍可以正常讀取堆內(nèi)容。 (4) 在釋放資源時(shí)才會(huì)發(fā)生異常。 (5) 如果點(diǎn)擊“中止”,則程序隨即停止;如果點(diǎn)擊“重試”,則進(jìn)入異常處理程序(說(shuō)明其實(shí)還是能捕獲到的,只是無(wú)法直接隱藏錯(cuò)誤窗口);如果點(diǎn)擊忽略,則程序繼續(xù)進(jìn)行。下圖依次顯示了點(diǎn)擊“中止”“重試”“忽略”的情況。
========== 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 );}
}
注意以下幾點(diǎn): (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 );}
}
注意以下幾點(diǎn): (1) 棧錯(cuò)誤即使加了異常處理語(yǔ)句,也會(huì)彈出錯(cuò)誤框。 (2) 當(dāng)棧頭部被修改后,仍可以正常讀取堆內(nèi)容。 (3) 在釋放資源時(shí)才會(huì)發(fā)生異常。 (4) 如果點(diǎn)擊“中止”,則程序隨即停止;如果點(diǎn)擊“重試”,則進(jìn)入異常處理程序(說(shuō)明其實(shí)還是能捕獲到的,只是無(wú)法直接隱藏錯(cuò)誤窗口);如果點(diǎn)擊忽略,則程序繼續(xù)進(jìn)行,仍會(huì)繼續(xù)拋出異常,再次點(diǎn)擊忽略,再次拋出異常,第三次點(diǎn)擊繼續(xù),程序進(jìn)入異常處理。下圖依次顯示了點(diǎn)擊“中止”“重試”“忽略”的情況。
========== 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 );}
}
注意以下幾點(diǎn): (1) 點(diǎn)擊兩次忽略后,程序結(jié)束。與棧頭部錯(cuò)誤有所區(qū)別。(可能因?yàn)轭^部指針沒(méi)有問(wèn)題,所以沒(méi)有報(bào)“_CrtIsValidHeapPointer(pUserData)”異常)
關(guān)于異常無(wú)法捕獲的補(bǔ)充材料請(qǐng)參考: Error的博文 Error的博文
總結(jié)
以上是生活随笔 為你收集整理的堆栈错误 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。