請(qǐng)先看一到程序:
程序試圖給長(zhǎng)度為10的字符串str拷貝超過10個(gè)長(zhǎng)度的字符串,不少初學(xué)者可能忘記了數(shù)組開辟的長(zhǎng)度或是沒有意識(shí)到越界的問題引發(fā)這樣的錯(cuò)誤寫法,可能更令新人詫異的是,這樣的寫的程序竟然編譯器不報(bào)錯(cuò),并且運(yùn)行也不報(bào)錯(cuò)! 大家可以自行嘗試運(yùn)行這個(gè)程序,不僅編譯沒有問題,運(yùn)行也看起來一切“正常”!
這就是一個(gè)典型的數(shù)組越界引發(fā)的問題,如果大家細(xì)心讀程序觀察結(jié)果,就會(huì)發(fā)現(xiàn)雖然str字符串的內(nèi)容沒有問題,但旁邊的整形變量a似乎有點(diǎn)“搶鏡”哦,原來是5,可現(xiàn)在竟然輸出0! 再看看代碼,又沒有被賦值,就莫名由5改成了0!真是躺著也中槍?。?/span>
那這里為什么a的值被更改了呢?下面我們?yōu)榇蠹以敿?xì)解釋!
若要查明這個(gè)原因,大家可以跟蹤內(nèi)存,尤其變量a的位置便可以查明一二。
如圖,Strcpy函數(shù)前下斷點(diǎn),首先確認(rèn)a的值和str的初始值:
a確認(rèn)是5沒有問題,由于str數(shù)組的地址我們觀察到比a要小,所以內(nèi)存監(jiān)視這里我們更新為str的地址,可以順便觀察str和它后面的a兩個(gè)值,如下圖:
可以看到str地址0x0019ff30處還未初始化,而a的地址為0x0019ff3c且初始化為5,沒有問題!
執(zhí)行下一步繼續(xù)觀察:
看到str數(shù)組已經(jīng)被初始化為0(紅色部分占10個(gè)字節(jié)),注意此時(shí)的a距離str最后一個(gè)元素也就是str[9]的位置也就三個(gè)字節(jié)! 現(xiàn)在大家可以偷偷再數(shù)一數(shù)strcpy給str拷貝的字符串長(zhǎng)度為12個(gè)…咳咳
那么繼續(xù)下一步,繼續(xù)觀察:
注意,問題來了! Strcpy這一步直接導(dǎo)致從0x0019ff30處開始的13個(gè)字節(jié)全部更改,并且波及到了a的地址0x0019ff3c處,仔細(xì)觀察分析內(nèi)容可以看到前12個(gè)分別為123456789123這12個(gè)數(shù)的ASC碼,而第13個(gè)字節(jié)的內(nèi)容則為字符串結(jié)尾的’\0’所致!使得第13個(gè)字節(jié)處的內(nèi)容也就是a的地址也被字符串末尾的\0進(jìn)行覆蓋,所以原來的5被0覆蓋!這就是a躺著也中槍的真實(shí)原因! 超長(zhǎng)的字符串加上結(jié)尾的\0使得下一個(gè)變量的值也受到了影響!
這就是數(shù)組越界引發(fā)的問題的實(shí)驗(yàn),希望對(duì)大家有幫助!
有問題歡迎指出!
C語言研究中心(www.sztianhecheng.cn)