• <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>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉(zhuǎn),開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            1: 段錯誤產(chǎn)生的原因

            簡而言之,產(chǎn)生段錯誤就是訪問了錯誤的內(nèi)存段,一般是你沒有權限,或者根本就不存在對應的物理內(nèi)存,
            尤其常見的是訪問0地址.一旦一個程序發(fā)生了越界訪問,系統(tǒng)就采取內(nèi)存保護措施,并給那個程序發(fā)送
            SIGSEGV信號,程序接到那個信號后就知道segmentation fault出現(xiàn)了。

            想對”段錯誤”有更詳細的了解可以去閱讀“Linux下的段錯誤產(chǎn)生的原因及調(diào)試方法” 這篇文章,本文的
            內(nèi)容基本是從那文章里提取出來的。

            2: SIGSEGV信號處理函數(shù)

            程序接到SIGSEGV信號后的缺省處理是退出程序,這也是為什么總是看到程序打印一個“segmentation fault”
            信息后就消失了。我們可以使用 signal(SIGSEGV, &your_function);函數(shù)來接管SIGSEGV信號的處理,讓
            程序在發(fā)生段錯誤后,自動調(diào)用我們準備好的函數(shù),從而在那個函數(shù)里來獲取當前函數(shù)調(diào)用棧。

            3: libc的Backtraces函數(shù)

            在GDB里,可以簡單的使用bt命令就可以獲取函數(shù)調(diào)用棧,但如何通過代碼獲取當前函數(shù)調(diào)用棧?
            這里我們可以通過libc庫提供的Backtraces系列函數(shù)

            A backtrace is a list of the function calls that are currently active in a
            thread. The usual way to inspect a backtrace of a program is to use an
            external debugger such as gdb. However, sometimes it is useful to
            obtain a backtrace programmatically from within a program, e.g., for the
            purposes of logging or diagnostics.
            ?
            The header file execinfo.h declares three functions that obtain and
            manipulate backtraces of the current thread.

            4: 實現(xiàn)步驟

            4.1 在你的工程中添加如下代碼:

            														#include <execinfo.h>
            														#include <stdio.h>
            														#include <stdlib.h>
            														#include <signal.h>
            ?
            void dump(int signo){void*array[30];
                size_t size;char**strings;
                size_t i;
            ?
                size = backtrace (array,30);
                strings = backtrace_symbols (array, size);
            ?
                fprintf (stderr,"Obtained %zd stack frames.nm", size);
            ?
                for(i =0; i < size; i++)
                    fprintf (stderr,"%sn", strings[i]);
            ?
                free (strings);
            ?
                exit(0);}
            ?
            Debug_Printf_FrameInfos(){
                signal(SIGSEGV,&dump);}

            4.2 在mian函數(shù)開始位置處調(diào)用 Debug_Printf_FrameInfos() 函數(shù)
            4.3 在編譯程序時 加上 -g 選項

            5 定位出錯函數(shù)地址實例

            這里以 test.c 為例,來查找出錯函數(shù)地址

            														#include <execinfo.h> 
            														#include <stdio.h>
            														#include <stdlib.h>
            														#include <signal.h>
            ?
            void dump(int signo){void*array[30];
                size_t size;char**strings;
                size_t i;
            ?
                size = backtrace (array,30);
                strings = backtrace_symbols (array, size);
            ?
                fprintf (stderr,"Obtained %zd stack frames.nm", size);
            ?
                for(i =0; i <= size; i++)
                    fprintf (stderr,"%s\n", strings[i]);
            ?
                free (strings);
                exit(0);}
            ?
            Debug_Printf_FrameInfos(){
                signal(SIGSEGV, dump);}
            ?
            void func_c(){*((volatilechar*)0x0)=0x999;}void func_b(){
                func_c();}void func_a(){
                func_b();}int main(){
                Debug_Printf_FrameInfos();
                func_a();return0;}

            該例程調(diào)用序列為:
            main() -> func_a() -> func_b() -> func_c() -> 出錯

            5.1編譯程序:

            # gcc -g test.c -o test

            注:選項 -rdynamic 可用來通知鏈接器將所有符號添加到動態(tài)符號表中,如果你的鏈接器支持-rdynamic的話,
            建議將其加上,即
            # gcc -rdynamic -g test.c -o test

            5.2 運行 test程序:

            														#  ./test
            Obtained 7 stack frames.nm./a.out [0x80484e3][0xb7f70420]
            ./a.out [0x804859d]
            ./a.out [0x80485a7]
            ./a.out [0x80485c4]/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7e1e450]
            ./a.out [0x8048461]
            Segmentation fault

            如果編譯似加了-rdynamic選項 的話,將打印如下信息

            														# ./test 
            Obtained 7 stack frames.nm./test(dump+0x1f)[0x80487c3][0xb7fbb420]
            ./test(func_b+0x8)[0x804887d]
            ./test(func_a+0x8)[0x8048887]
            ./test(main+0x1b)[0x80488a4]/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7e69450]
            ./test[0x8048741]

            打印信息比沒加-rdynamic的程序多出了一個函數(shù)名稱+偏移地址..(func_b+0×8)

            5.3 使用objdump獲取程序所有符合

            objdump -d ./test > tmp.txt

            5.4 分析和查找

            在tmp.txt 中查找0×80485ad的地址,你會發(fā)現(xiàn)如下信息:
            08048595 :
            8048595: 55 push %ebp
            8048596: 89 e5 mov %esp,%ebp
            8048598: e8 eb ff ff ff call 8048588
            804859d: 5d pop %ebp
            804859e: c3

            其中 804859d 是調(diào)用( call 8048588 )c函數(shù)后的地址,雖然并沒有直接定位到C函數(shù),
            通過匯編代碼,基本可以推出是在C函數(shù)出現(xiàn)問題了。(pop指令不會導致段錯誤的)

            本文最早發(fā)布在 我的CSDN blog上。

            本文地址:
            http://www.kgdb.info/linuxdev/backtrace_without_gdb/
            版權所有 ? 轉(zhuǎn)載時必須以鏈接形式注明作者和原始出處!

            www.久久精品| 久久久无码精品亚洲日韩软件| 热综合一本伊人久久精品| 久久人人爽人人爽人人片AV麻豆 | 中文字幕久久欲求不满| 国产综合成人久久大片91| 伊人色综合久久天天人守人婷| 久久人人妻人人爽人人爽| 9999国产精品欧美久久久久久| 中文字幕精品无码久久久久久3D日动漫 | 国产成年无码久久久久毛片| 99精品久久久久久久婷婷| 日日狠狠久久偷偷色综合96蜜桃| 久久精品卫校国产小美女| 久久精品成人免费看| 久久精品国产2020| 久久国产成人精品国产成人亚洲| 久久强奷乱码老熟女网站| 国产精品久久久久一区二区三区 | a高清免费毛片久久| 亚洲精品视频久久久| 国内精品免费久久影院| 99久久99久久久精品齐齐| 四虎国产精品成人免费久久| 久久精品国产一区二区三区| 97r久久精品国产99国产精| 久久久一本精品99久久精品88| 精品国产青草久久久久福利| 国产精品久久国产精麻豆99网站| 久久伊人五月丁香狠狠色| 久久这里只精品99re66| 久久久久亚洲精品天堂久久久久久| 97久久超碰成人精品网站| 欧美午夜精品久久久久免费视| 日韩久久久久中文字幕人妻| 香港aa三级久久三级| 99久久精品国产毛片| 久久66热人妻偷产精品9| 久久人人爽人人爽人人片av高请| 色狠狠久久AV五月综合| 狠狠色丁香久久婷婷综合五月|