天天看點

Linux學習----gdb調試(指針的指針)

昨天遇到一個很奇怪的問題,如下:

按照理論,最後*p的值應該是99,不知為什麼是15了,是以今天記錄用gdb調試的過程,并熟悉gdb的使用。

(調試過程參考:http://www.cnblogs.com/hankers/archive/2012/12/07/2806836.html) 

開始:

1.

2.(用list從第1行開始列出源碼)

3.(一次隻列10行,如果要從第11行開始繼續列源代碼可以輸入list)

4.(也可以什麼都不輸直接敲回車,

gdb

提供了一個很友善的功能,在提示符下直接敲回車表示重複上一條指令。)

5.(

gdb

的很多常用指令有簡寫形式,例如

list

指令可以寫成

l

,要列一個函數的源代碼也可以用函數名做參數:)

6.(退出gdb環境)

7.(現在将niuke.cpp改名,然後gdb就列不出源碼了)

說明:

gcc

-g

選項并不是把源代碼嵌入到可執行檔案中的,在調試時也需要源檔案。

8.(源碼檔案恢複,重新開始)

gdb

停在

main

函數中變量定義之後的第一條語句處等待我們發指令,

gdb

列出的這條語句是即将執行的下一條語句。

9.(我們可以用

next

指令(簡寫為

n

)控制這些語句一條一條地執行)

說明:用n函數f()中的結果一下就列印出來了

 10.(現在用start重新開始,用step指令(簡寫s)進入f()中去跟蹤執行)

現在進入了f()函數。

 11.(在函數中有幾種檢視狀态的辦法,

backtrace

指令(簡寫為

bt

)可以檢視函數調用的棧幀)

可見目前f()是被main()調用的,傳入指針p傳給ret=0xbfffee94

12.(檢視目前f()函數内局部變量的值i locals 或者info locals)

13.(如果想檢視

main

函數目前局部變量的值也可以做到,先用

frame

指令(簡寫為

f

)選擇1号棧幀然後再檢視局部變量,i locals, info locals)

14.(繼續運作,然後用p+變量名檢視變量的值)

這裡......$5,$6,$7,$8......分别儲存了檢視的中間值:

未執行*ret = &a時:

ret: 0xbfffee94(為&p)  *ret:0xbfffef54(p)  **ret:-1073745577

執行*ret = &a後:

ret: 0xbfffee94  *ret:0xbfffee68 = &a:0xbfffee68(值為99)  **ret:99(等于a)

15.(finish指令讓程式一直運作到目前函數結束) 

傳回值是ret=0xbfffee94(&p)

16.(現在繼續運作)

注意:A &p address : 0xbfffee94(&p未改變)  A p address : 0xbfffee68(與&a相同)  A *p value   : 15(奇怪的地方,為什麼不是99)

17.(換一種思路:在執行 cout << "A &p address : " << &p << endl; 之前直接檢視*p)

這裡可以看到*p=99,是正确的,位址也與上面相同

18.(繼續調試)

這裡發現*p=15,被改變了。

 也就是說:在執行cout << "A &p address : " << &p << endl;後, *p的值被改變了,從99變為15了。

 19.(連續輸出兩次*p)

這次發現第一次輸出結果正常,第二次輸出結果出錯,那為什麼呢?為什麼呢?????

20.(知道原因了)

說明:a是一個局部變量,&a在f()執行完後就被系統回收了。f()中ret = &a 這一步,使得p=&a,是以最後p輸出不對。      

修改後:

這裡終于正确了。

PS:前面一種情況,棧被系統回收,但是仍能輸出一次99,我猜可能是系統還沒來的及回收。。。

PSS:指針太容易出錯了。。