• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            elva

            關于DBG加載core文件

            2.6 調試

            2.6.1 調試器

              FreeBSD 自帶的調試器叫 gdb (GNU debugger)。要運行,輸入

            % gdb progname
            

              然而大多數(shù)人喜歡在 Emacs 中運行這個命令。 可以這樣來起動這個命令:

            M-x gdb RET progname RET
            

              調試器能讓你在一個可控制的環(huán)境中運行一個程序。例如,你可以一次運行程 序的一行代碼,檢查變量的值,改變這些值,或者讓程序運行到某個定點然后停止等 等。你甚至可以調試內(nèi)核,當然這樣會比我們將要討論的問題要多一點點技巧。

              gdb 有非常棒的在線幫助,還有同樣棒的 info 頁面。 因此這一章我們會把注意力集中到一些基本的命令上。

              最后,如果你不習慣這個命令的命令行界面,在 Ports 中還有一個它的圖形 前端 (devel/xxgdb)。

              這一章準備只介紹 gdb 的使用方法,而不會牽涉到特殊 的問題比如調試內(nèi)核。

            2.6.2 在調試器中運行一個程序

              要最大限度的利用 gdb,需要使用 -g 這個選項來編譯你的程序。如果你沒有這樣做,那么你只會看 到你正在調試的函數(shù)名字,而不是它的源代碼。如果 gdb起動 時提示:

            ... (no debugging symbols found) ...
            

              你就知道你的程序在編譯的時候沒有使用 -g 選項。

              當 gdb 給出提示符,輸入 break main。 這就是告訴調試器你對正在運行的程序中預先設置的代碼沒有興趣, 并且調試器應該停在你的代碼的開頭。然后輸入 run 來開始你的程序──這會從 預先設置的代碼開始然后在調試器調用 main() 的時候就停 下來。(如果你曾迷惑 main() 是在哪里被調用的,現(xiàn)在應該 明白了吧!)

              現(xiàn)在你可以一步一步來檢查你的程序,按下 n一次就查 一行。一旦你碰見了一個函數(shù)調用,可以輸入 f 從函數(shù)調用中 退出來。你可以輸入 up或 down 來快速 檢查這個調用。

              這里列出了一個簡單的例子。展示了怎樣用 gdb 定位一個錯 誤。這是我們的程序(其中有一個明顯的錯誤):

            #include <stdio.h>
            
            int bazz(int anint);
            
            main() {
                int i;
            
                printf("This is my program\n");
                bazz(i);
                return 0;
            }
            
            int bazz(int anint) {
                printf("You gave me %d\n", anint);
                return anint;
            }
            

              這個程序給 i 賦值 5 并把它傳遞給 一個函數(shù) bazz(),這個函數(shù)將打印出我們給出的數(shù)值。

              我們現(xiàn)在編譯并運行這個程序,我們會得到

            % cc -g -o temp temp.c
            % ./temp
            This is my program
            anint = 4231
            

              但這并不是我們想要的!應該看看到底發(fā)生了什么!

            % gdb temp
            GDB is free software and you are welcome to distribute copies of it
             under certain conditions; type "show copying" to see the conditions.
            There is absolutely no warranty for GDB; type "show warranty" for details.
            GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
            (gdb) break main               Skip the set-up code
            Breakpoint 1 at 0x160f: file temp.c, line 9.    gdb puts breakpoint at main()
            (gdb) run                   Run as far as main()
            Starting program: /home/james/tmp/temp      Program starts running
            
            Breakpoint 1, main () at temp.c:9       gdb stops at main()
            (gdb) n                       Go to next line
            This is my program              Program prints out
            (gdb) s                       step into bazz()
            bazz (anint=4231) at temp.c:17          gdb displays stack frame
            (gdb)
            

              停住!怎么 anint 會是 4231?難道 我們沒有在函數(shù) main() 中設定為 5 嗎?現(xiàn)在我們轉到 main() 來看看。

            (gdb) up                   Move up call stack
            #1  0x1625 in main () at temp.c:11      gdb displays stack frame
            (gdb) p i                   Show us the value of i
            $1 = 4231                   gdb displays 4231
            

              哦,天哪!看看這代碼,我們忘了初始化 i 了。本來我們 是想的

            ...
            main() {
                int i;
            
                i = 5;
                printf("This is my program\n");
            ...
            

              但是我們忘了 i=5; 這一行。因為我們沒有初始化 i,這個變量在程序運行的時候就儲存了偶然在那塊內(nèi)存中存在的 任意值。

            注意: gdb 會顯示我們進入或離開一個函數(shù)時的棧的值。即 使是我們在使用 up 或 down 的時候。 這會顯示函數(shù)的名稱還有參數(shù)的值,讓我們知道自己的位置以及正在發(fā)生什么事情。 (棧能儲存程序在調用函數(shù)的時使用的參數(shù),以及調用時的位置,以便程序在從函 數(shù)調用結束后知道自己的位置。)

            2.6.3 檢查 core 文件

              基本上 core 文件就是一個包含了程序崩潰時這個進程的所有信息的文件。在那 “遙遠的黃金年代”,程序員不得不把 core 文件以十六進制的方式顯示 出來,然后滿頭大汗的閱讀機器碼的手冊,但是現(xiàn)在事情就簡單得多了。順便說一下, 在 FreeBSD 和其他的 4.4BSD 系統(tǒng)下,core 文件都叫作 progname.core 而不是簡單叫 core,這樣可以很清楚的表示出這個 core 文件是屬于哪個 程序。

              要檢查一個 core 文件,以通常的方式起動 gdb。不要 輸入 break 或者 run,而要輸入

            (gdb) core progname.core
            

              如果你沒有和 core 文件在同一個目錄,首先要執(zhí)行 dir /path/to/core/file

              你應該可以看見:

            % gdb a.out
            GDB is free software and you are welcome to distribute copies of it
             under certain conditions; type "show copying" to see the conditions.
            There is absolutely no warranty for GDB; type "show warranty" for details.
            GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
            (gdb) core a.out.core
            Core was generated by `a.out'.
            Program terminated with signal 11, Segmentation fault.
            Cannot access memory at address 0x7020796d.
            #0  0x164a in bazz (anint=0x5) at temp.c:17
            (gdb)
            

              這種情況下,運行的程序叫 a.out,因此 core 文件 就叫 a.out.core。我們知道程序崩潰的原因就是函數(shù) bazz 試圖訪問一塊不屬于它的內(nèi)存。

              有時候,能知道一個函數(shù)是怎么被調用的是非常有用處的。因為在一個復雜的 程序里面問題可能會發(fā)生在函數(shù)調用棧上面很遠的地方。命令bt 會讓 gdb 輸出函數(shù)調用棧的回溯追蹤。

            (gdb) bt
            #0  0x164a in bazz (anint=0x5) at temp.c:17
            #1  0xefbfd888 in end ()
            #2  0x162c in main () at temp.c:11
            (gdb)
            

              函數(shù) end() 在一個程序崩潰的時候將被調用;在本例 中,函數(shù) bazz() 是從 main() 中被 調用的。

            2.6.4 粘付到一個正在運行的程序

              gdb 一個最精致的特性就是它能粘付到一個已經(jīng)在運行 的程序上。當然,我們得首先假定你有足夠的權限這樣去做。一個常見的問題就是, 當我們在追蹤一個包含子進程的程序時,如果你要追蹤子進程,但是調試器只允許你 追蹤父進程。

              你要做的就是起動另一個 gdb,然后用 ps 找出子進程的進程號。然后在 gdb中執(zhí)行

            (gdb) attach pid
            

              就可以像平時一樣調試了。

              “這很好,”你可能在想,“當我這樣做了以后,子進程就 會不見了”。別怕,親愛的讀者,我們可以這樣來做(參照 gdb 的 info 頁)

            ...
            if ((pid = fork()) < 0)      /* _Always_ check this */
                error();
            else if (pid == 0) {        /* child */
                int PauseMode = 1;
            
                while (PauseMode)
                    sleep(10);  /* Wait until someone attaches to us */
                ...
            } else {            /* parent */
                ...
            

              現(xiàn)在所有你要做的就是粘付到子進程,設置 PauseMode 為 0,然后等待函數(shù) sleep 返回!

            posted on 2010-08-06 12:03 葉子 閱讀(1055) 評論(0)  編輯 收藏 引用 所屬分類: C\C++

            久久亚洲sm情趣捆绑调教| 久久99精品国产麻豆宅宅| 国产成人精品久久亚洲| 久久夜色撩人精品国产| 狠狠色丁香久久婷婷综合| 国产精品美女久久久久网| 人妻系列无码专区久久五月天| 亚洲精品成人网久久久久久| 久久午夜羞羞影院免费观看| 国产精品欧美亚洲韩国日本久久| 久久这里有精品| 7国产欧美日韩综合天堂中文久久久久| 99久久精品免费国产大片| 久久久久久久久久久久久久| 国产精品久久久久久福利69堂| 亚洲国产成人精品无码久久久久久综合 | 久久夜色tv网站| 97久久婷婷五月综合色d啪蜜芽| 色综合色天天久久婷婷基地| 一本色道久久99一综合| 久久亚洲AV永久无码精品| 久久免费精品一区二区| 人妻无码αv中文字幕久久| 欧美色综合久久久久久| 99久久国产免费福利| 久久亚洲精品中文字幕| 久久99久国产麻精品66| 一个色综合久久| 久久精品国产亚洲精品| 国内精品久久久久国产盗摄| 亚洲国产成人久久综合碰碰动漫3d| 色综合久久久久无码专区| 久久久久久久综合狠狠综合| 久久国产精品视频| 国产精品午夜久久| 久久国产午夜精品一区二区三区| 亚洲狠狠综合久久| 国产91久久综合| 日本亚洲色大成网站WWW久久| 久久久久亚洲精品男人的天堂| 久久综合伊人77777麻豆|