June 17, 2010

在 GDB 透視 C 語言的字串表示法

最近從「快快樂樂學 GDB」到一系列與 C 程式語言相關的 [演講議程],探討了在執行時期,透過 GDB 一窺系統全貌的途徑。筆者的觀點是,C 程式語言就是設計來開發作業系統的用途,務必確認每個環節。UNIX 之父 Ken Thompson,不僅開創了 UNIX 若干經典的設計,也持續維護 C compiler,甚至在 Plan9 研發時,還重新翻修過整個編譯系統的設計,可參考 [A New C Compiler by Ken Thompson],顯然就是不放過任何一個技術細節。身處於 21 世紀的我們,幸福多了,有強大的 GDB 搭配開放的 GNU/Linux,而本文就在這些基礎上,談談在 GDB 透視 C 語言的字串表示法。

前文 [C-style 字串的最佳化] 提過 C 語言字串的形式,其實不過是一段保存於連續記憶體的資料,那面對稍微複雜一些的形式,我們不免會亂了方寸,這時候當然要祭出 GNU gdb 來協助。首先,我們先讓 gdb 變身為 C interpreter:
$ gdb `which gdb`
GNU gdb (GDB) 7.1-ubuntu
[...略...]
Reading symbols from /usr/bin/gdb...(no debugging symbols found)...done.
(gdb) start
Temporary breakpoint 1 at 0x808ae03
Starting program: /usr/bin/gdb 
[Thread debugging using libthread_db enabled]

Temporary breakpoint 1, 0x0808ae03 in main ()
(gdb)
取得 gdb 的命令提示列後,就可動態作許多 C 語言版本的 eval (可對比 JavaScript 的 eval),我們接著作個實驗:
(gdb) p (char (*) [10]) &"0123456789abcdefghi"
$1 = (char (*)[10]) 0x83ca008
注意到字串 "0123456789abcdefghi" 的動態宣告方式與提取記憶體位址 (operator &) 的寫法,在 gdb 必須清楚的標示 C 語言的 type casting。我們知曉這 10 個單位的 C-style 字串陣列,被配置到自位址 0x83ca008 開始的連續記憶體,那就分別來窺探記憶體的內容:
(gdb) p ((char (*) [10]) &"0123456789abcdefghi")[0]
$2 = "0123456789"
(gdb) p ((char (*) [10]) &"0123456789abcdefghi")[1]
$3 = "abcdefghi"
當然,你也可以這麼作:(想想輸出的結果為何如此)
(gdb) p (char[]) {"abcdefghi"}
$4 = "P"
或者:
(gdb) p (const char[]) "abcdefghi"
$5 = "abcdefghi
前後比對 "char *" 與 "char[]" 對應的記憶體關聯,也可發現兩者的微妙差異,一切都經由 gdb 攤在陽光底下。
由 jserv 發表於 June 17, 2010 12:34 AM
迴響
發表迴響









記住我的資訊?