2012年軟件水平設(shè)計(jì)師:C語(yǔ)言編程常見(jiàn)BUG
記錄一些C語(yǔ)言易出的bug,有些是自己編程中遇到的,有些是在其他地方看到的:
1、釋放動(dòng)態(tài)內(nèi)存時(shí)遇到“user breakpoint called from code at 0x********”
這個(gè)bug多在調(diào)用free函數(shù)來(lái)釋放malloc的內(nèi)存時(shí)出現(xiàn),前先曾多次遇到,但一直未找出問(wèn)題原因。
在網(wǎng)上查了一下,有些寫(xiě)得挺復(fù)雜,涉及到了操作系統(tǒng)推維護(hù)的內(nèi)容,現(xiàn)在還不有接觸到這一塊,所以沒(méi)有細(xì)看。其他有說(shuō)到重復(fù)釋放動(dòng)態(tài)內(nèi)存,修改動(dòng)態(tài)內(nèi)存指針或者破壞了系統(tǒng)的動(dòng)態(tài)內(nèi)存結(jié)束標(biāo)志都會(huì)導(dǎo)致這個(gè)bug。后來(lái)查看自己的代碼,發(fā)現(xiàn)重復(fù)釋放的問(wèn)題倒是沒(méi)有,卻在操作內(nèi)存時(shí)有一處頻繁操作超出動(dòng)態(tài)申請(qǐng)內(nèi)存之外的單元,故導(dǎo)致這個(gè)問(wèn)題的出現(xiàn)。
問(wèn)題總結(jié):在動(dòng)態(tài)內(nèi)存釋放時(shí)出現(xiàn),多由于動(dòng)態(tài)內(nèi)存使用不當(dāng)
1、重復(fù)釋放動(dòng)態(tài)內(nèi)存
2、讀寫(xiě)操作超出了動(dòng)態(tài)申請(qǐng)內(nèi)存邊界(讀應(yīng)該不會(huì)發(fā)生問(wèn)題,但也要避免,除非你真正明白自己在干什么)
2、C中的字符串異常
嚴(yán)格地說(shuō),C中是沒(méi)有字符串變量的,一般采用字符數(shù)組或字符指針的方式才實(shí)現(xiàn)字符串的操作,二者在使用中有諸多類(lèi)似,但并不是完全等價(jià)的,注意下面兩句的區(qū)別:
char a[] = “Hello world”;//存放在棧中,可以修改a數(shù)據(jù)組的任意值
char *s = “Hello world”;//指針s存放在棧中,字符串常量在代碼段,不可修改
給s[i]賦值將導(dǎo)致錯(cuò)誤
3、條件判斷時(shí)一定要學(xué)會(huì)利用短路特性來(lái)防止異常,如
while(j 》=0 && a[j] 》0) j--;
if(d != 0 && n/d == 0)
if(p == NULL || *p == ’\0‘)/*no string*/
例中3種情況或?qū)蓚€(gè)判斷條件調(diào)換了次序都會(huì)導(dǎo)致內(nèi)存溢出。
4、關(guān)于混亂的類(lèi)型擴(kuò)展問(wèn)題
因?yàn)椴淮_定編譯器采用哪種保護(hù)規(guī)則(無(wú)符號(hào)保護(hù)或是值保護(hù)),應(yīng)盡量避免在同一個(gè)表達(dá)式內(nèi)混用有符號(hào)和無(wú)符號(hào)的變量。任何時(shí)候,總可以用顯式的類(lèi)型轉(zhuǎn)換來(lái)明確無(wú)誤地表達(dá)所希望的轉(zhuǎn)換的地方或方式。
5、類(lèi)型轉(zhuǎn)換被當(dāng)成左值
在C語(yǔ)言中,類(lèi)型轉(zhuǎn)換操作只能生成一個(gè)右值,不能被賦值或進(jìn)行自增(減)運(yùn)算。
如
char *p;
((int *)p)++;
不能完成預(yù)想中的將p增加一個(gè)int的長(zhǎng)度,而應(yīng)該如下:
p= (char *)((int *)p + 1);
或p += sizeof(int);
6、變長(zhǎng)參數(shù)函數(shù)調(diào)用中,會(huì)進(jìn)行默認(rèn)類(lèi)型轉(zhuǎn)換嗎?
下面這段代碼的輸出是什么?
#include 《stdio.h》
int main()
{
__int64 n;
int b;
n = 1;
b = 2;
printf(“%d,%d\n”,n,b);
return 0;
}
和預(yù)料不同的是,它輸出:1,0
這是因?yàn)樵诳勺儏?shù)函數(shù)調(diào)用中,一般編譯器是不進(jìn)行默認(rèn)類(lèi)型轉(zhuǎn)換的,當(dāng)函數(shù)根據(jù)格式字符串從棧中提取參數(shù)時(shí)就會(huì)由于變量長(zhǎng)度不一致而產(chǎn)生異常的輸出。
記錄一些C語(yǔ)言易出的bug,有些是自己編程中遇到的,有些是在其他地方看到的:
1、釋放動(dòng)態(tài)內(nèi)存時(shí)遇到“user breakpoint called from code at 0x********”
這個(gè)bug多在調(diào)用free函數(shù)來(lái)釋放malloc的內(nèi)存時(shí)出現(xiàn),前先曾多次遇到,但一直未找出問(wèn)題原因。
在網(wǎng)上查了一下,有些寫(xiě)得挺復(fù)雜,涉及到了操作系統(tǒng)推維護(hù)的內(nèi)容,現(xiàn)在還不有接觸到這一塊,所以沒(méi)有細(xì)看。其他有說(shuō)到重復(fù)釋放動(dòng)態(tài)內(nèi)存,修改動(dòng)態(tài)內(nèi)存指針或者破壞了系統(tǒng)的動(dòng)態(tài)內(nèi)存結(jié)束標(biāo)志都會(huì)導(dǎo)致這個(gè)bug。后來(lái)查看自己的代碼,發(fā)現(xiàn)重復(fù)釋放的問(wèn)題倒是沒(méi)有,卻在操作內(nèi)存時(shí)有一處頻繁操作超出動(dòng)態(tài)申請(qǐng)內(nèi)存之外的單元,故導(dǎo)致這個(gè)問(wèn)題的出現(xiàn)。
問(wèn)題總結(jié):在動(dòng)態(tài)內(nèi)存釋放時(shí)出現(xiàn),多由于動(dòng)態(tài)內(nèi)存使用不當(dāng)
1、重復(fù)釋放動(dòng)態(tài)內(nèi)存
2、讀寫(xiě)操作超出了動(dòng)態(tài)申請(qǐng)內(nèi)存邊界(讀應(yīng)該不會(huì)發(fā)生問(wèn)題,但也要避免,除非你真正明白自己在干什么)
2、C中的字符串異常
嚴(yán)格地說(shuō),C中是沒(méi)有字符串變量的,一般采用字符數(shù)組或字符指針的方式才實(shí)現(xiàn)字符串的操作,二者在使用中有諸多類(lèi)似,但并不是完全等價(jià)的,注意下面兩句的區(qū)別:
char a[] = “Hello world”;//存放在棧中,可以修改a數(shù)據(jù)組的任意值
char *s = “Hello world”;//指針s存放在棧中,字符串常量在代碼段,不可修改
給s[i]賦值將導(dǎo)致錯(cuò)誤
3、條件判斷時(shí)一定要學(xué)會(huì)利用短路特性來(lái)防止異常,如
while(j 》=0 && a[j] 》0) j--;
if(d != 0 && n/d == 0)
if(p == NULL || *p == ’\0‘)/*no string*/
例中3種情況或?qū)蓚€(gè)判斷條件調(diào)換了次序都會(huì)導(dǎo)致內(nèi)存溢出。
4、關(guān)于混亂的類(lèi)型擴(kuò)展問(wèn)題
因?yàn)椴淮_定編譯器采用哪種保護(hù)規(guī)則(無(wú)符號(hào)保護(hù)或是值保護(hù)),應(yīng)盡量避免在同一個(gè)表達(dá)式內(nèi)混用有符號(hào)和無(wú)符號(hào)的變量。任何時(shí)候,總可以用顯式的類(lèi)型轉(zhuǎn)換來(lái)明確無(wú)誤地表達(dá)所希望的轉(zhuǎn)換的地方或方式。
5、類(lèi)型轉(zhuǎn)換被當(dāng)成左值
在C語(yǔ)言中,類(lèi)型轉(zhuǎn)換操作只能生成一個(gè)右值,不能被賦值或進(jìn)行自增(減)運(yùn)算。
如
char *p;
((int *)p)++;
不能完成預(yù)想中的將p增加一個(gè)int的長(zhǎng)度,而應(yīng)該如下:
p= (char *)((int *)p + 1);
或p += sizeof(int);
6、變長(zhǎng)參數(shù)函數(shù)調(diào)用中,會(huì)進(jìn)行默認(rèn)類(lèi)型轉(zhuǎn)換嗎?
下面這段代碼的輸出是什么?
#include 《stdio.h》
int main()
{
__int64 n;
int b;
n = 1;
b = 2;
printf(“%d,%d\n”,n,b);
return 0;
}
和預(yù)料不同的是,它輸出:1,0
這是因?yàn)樵诳勺儏?shù)函數(shù)調(diào)用中,一般編譯器是不進(jìn)行默認(rèn)類(lèi)型轉(zhuǎn)換的,當(dāng)函數(shù)根據(jù)格式字符串從棧中提取參數(shù)時(shí)就會(huì)由于變量長(zhǎng)度不一致而產(chǎn)生異常的輸出。

