青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

每天早晨叫醒你的不是鬧鐘,而是夢想

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  62 Posts :: 0 Stories :: 5 Comments :: 0 Trackbacks

常用鏈接

留言簿(1)

我參與的團隊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

我們在用C/C++語言寫程序的時侯,內存管理的絕大部分工作都是需要我們來做的。實際上,內存管理是一個比較繁瑣的工作,無論你多高明,經驗多豐富,難免會在此處犯些小錯誤,而通常這些錯誤又是那么的淺顯而易于消除。但是手工“除蟲”(debug),往往是效率低下且讓人厭煩的,本文將就"段錯誤"這個內存訪問越界的錯誤談談如何快速定位這些"段錯誤"的語句。
下面將就以下的一個存在段錯誤的程序介紹幾種調試方法:
     1  dummy_function (void)
     2  {
     3          unsigned char *ptr = 0x00;
     4          *ptr = 0x00;
     5  }
     6
     7  int main (void)
     8  {
     9          dummy_function ();
    10
    11          return 0;
    12  }
作為一個熟練的C/C++程序員,以上代碼的bug應該是很清楚的,因為它嘗試操作地址為0的內存區域,而這個內存區域通常是不可訪問的禁區,當然就會出錯了。我們嘗試編譯運行它:
xiaosuo@gentux test $ ./a.out
段錯誤
果然不出所料,它出錯并退出了。
1.利用gdb逐步查找段錯誤:
這種方法也是被大眾所熟知并廣泛采用的方法,首先我們需要一個帶有調試信息的可執行程序,所以我們加上“-g -rdynamic"的參數進行編譯,然后用gdb調試運行這個新編譯的程序,具體步驟如下:
xiaosuo@gentux test $ gcc -g -rdynamic d.c
xiaosuo@gentux test $ gdb ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or 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.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) r
Starting program: /home/xiaosuo/test/a.out

Program received signal SIGSEGV, Segmentation fault.
0x08048524 in dummy_function () at d.c:4
4               *ptr = 0x00;
(gdb)                      
哦?!好像不用一步步調試我們就找到了出錯位置d.c文件的第4行,其實就是如此的簡單。
從這里我們還發現進程是由于收到了SIGSEGV信號而結束的。通過進一步的查閱文檔(man 7 signal),我們知道SIGSEGV默認handler的動作是打印”段錯誤"的出錯信息,并產生Core文件,由此我們又產生了方法二。
2.分析Core文件:
Core文件是什么呢?
The  default action of certain signals is to cause a process to terminate and produce a core dump file, a disk file containing an image of the process's memory  at the time of termination.  A list of the signals which cause a process to dump core can be found in signal(7).
以上資料摘自man page(man 5 core)。不過奇怪了,我的系統上并沒有找到core文件。后來,憶起為了漸少系統上的拉圾文件的數量(本人有些潔癖,這也是我喜歡Gentoo的原因之一),禁止了core文件的生成,查看了以下果真如此,將系統的core文件的大小限制在512K大小,再試:
xiaosuo@gentux test $ ulimit -c
0
xiaosuo@gentux test $ ulimit -c 1000
xiaosuo@gentux test $ ulimit -c
1000
xiaosuo@gentux test $ ./a.out
段錯誤 (core dumped)
xiaosuo@gentux test $ ls
a.out  core  d.c  f.c  g.c  pango.c  test_iconv.c  test_regex.c
core文件終于產生了,用gdb調試一下看看吧:
xiaosuo@gentux test $ gdb ./a.out core
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or 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.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".


warning: Can't read pathname for load map: 輸入/輸出錯誤.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0  0x08048524 in dummy_function () at d.c:4
4               *ptr = 0x00;
哇,好歷害,還是一步就定位到了錯誤所在地,佩服一下Linux/Unix系統的此類設計。
接著考慮下去,以前用windows系統下的ie的時侯,有時打開某些網頁,會出現“運行時錯誤”,這個時侯如果恰好你的機器上又裝有windows的編譯器的話,他會彈出來一個對話框,問你是否進行調試,如果你選擇是,編譯器將被打開,并進入調試狀態,開始調試。
Linux下如何做到這些呢?我的大腦飛速地旋轉著,有了,讓它在SIGSEGV的handler中調用gdb,于是第三個方法又誕生了:
3.段錯誤時啟動調試:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

void dump(int signo)
{
        char buf[1024];
        char cmd[1024];
        FILE *fh;

        snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());
        if(!(fh = fopen(buf, "r")))
                exit(0);
        if(!fgets(buf, sizeof(buf), fh))
                exit(0);
        fclose(fh);
        if(buf[strlen(buf) - 1] == '\n')
                buf[strlen(buf) - 1] = '\0';
        snprintf(cmd, sizeof(cmd), "gdb %s %d", buf, getpid());
        system(cmd);

        exit(0);
}

        void
dummy_function (void)
{
        unsigned char *ptr = 0x00;
        *ptr = 0x00;
}

        int
main (void)
{
        signal(SIGSEGV, &dump);
        dummy_function ();

        return 0;
}
編譯運行效果如下:
xiaosuo@gentux test $ gcc -g -rdynamic f.c
xiaosuo@gentux test $ ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or 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.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

Attaching to program: /home/xiaosuo/test/a.out, process 9563
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0  0xffffe410 in __kernel_vsyscall ()
#1  0xb7ee4b53 in waitpid () from /lib/libc.so.6
#2  0xb7e925c9 in strtold_l () from /lib/libc.so.6
#3  0x08048830 in dump (signo=11) at f.c:22
#4  <signal handler called>
#5  0x0804884c in dummy_function () at f.c:31
#6  0x08048886 in main () at f.c:38
怎么樣?是不是依舊很酷?
以上方法都是在系統上有gdb的前提下進行的,如果沒有呢?其實glibc為我們提供了此類能夠dump棧內容的函數簇,詳見/usr/include/execinfo.h(這些函數都沒有提供man page,難怪我們找不到),另外你也可以通過gnu的手冊進行學習。
4.利用backtrace和objdump進行分析:
重寫的代碼如下:
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

/* A dummy function to make the backtrace more interesting. */
        void
dummy_function (void)
{
        unsigned char *ptr = 0x00;
        *ptr = 0x00;
}

void dump(int signo)
{
        void *array[10];
        size_t size;
        char **strings;
        size_t i;

        size = backtrace (array, 10);
        strings = backtrace_symbols (array, size);

        printf ("Obtained %zd stack frames.\n", size);

        for (i = 0; i < size; i++)
                printf ("%s\n", strings[i]);

        free (strings);

        exit(0);
}

        int
main (void)
{
        signal(SIGSEGV, &dump);
        dummy_function ();

        return 0;
}
編譯運行結果如下:
xiaosuo@gentux test $ gcc -g -rdynamic g.c
xiaosuo@gentux test $ ./a.out
Obtained 5 stack frames.
./a.out(dump+0x19) [0x80486c2]
[0xffffe420]
./a.out(main+0x35) [0x804876f]
/lib/libc.so.6(__libc_start_main+0xe6) [0xb7e02866]
./a.out [0x8048601]
這次你可能有些失望,似乎沒能給出足夠的信息來標示錯誤,不急,先看看能分析出來什么吧,用objdump反匯編程序,找到地址0x804876f對應的代碼位置:
xiaosuo@gentux test $ objdump -d a.out

 8048765:       e8 02 fe ff ff          call   804856c <signal@plt>
 804876a:       e8 25 ff ff ff          call   8048694 <dummy_function>
 804876f:       b8 00 00 00 00          mov    $0x0,%eax
 8048774:       c9                      leave
我們還是找到了在哪個函數(dummy_function)中出錯的,信息已然不是很完整,不過有總比沒有好的啊!
后記:
本文給出了分析"段錯誤"的幾種方法,不要認為這是與孔乙己先生的"回"字四種寫法一樣的哦,因為每種方法都有其自身的適用范圍和適用環境,請酌情使用,或遵醫囑。
posted on 2011-04-14 22:14 沛沛 閱讀(274) 評論(0)  編輯 收藏 引用 所屬分類: C++
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美色道久久88综合亚洲精品| 国产精品久久久久9999高清| 国产精品中文在线| 另类激情亚洲| 久久人人爽国产| 老司机精品视频网站| 亚洲国产一成人久久精品| 日韩亚洲一区二区| 国产日韩欧美一二三区| 久久不见久久见免费视频1| 久久久久久一区| 日韩午夜在线播放| 精品不卡一区| 国产精品卡一卡二卡三| 亚洲高清免费在线| 欧美日韩视频| 久久久999| 久久久久久久成人| 欧美成人午夜剧场免费观看| 一本综合久久| 欧美激情二区三区| 老司机免费视频久久| 午夜视频精品| 亚洲欧美资源在线| 欧美午夜一区| 亚洲欧洲精品一区二区精品久久久| 亚洲精品日韩在线观看| 9久re热视频在线精品| 国产性猛交xxxx免费看久久| 在线观看av一区| 欧美在线视频免费| 午夜欧美不卡精品aaaaa| 99re6热只有精品免费观看| 久久久噜噜噜久久中文字幕色伊伊| 欧美sm重口味系列视频在线观看| 久久久久九九九| 宅男噜噜噜66国产日韩在线观看| 欧美在线亚洲在线| 国产精品爱啪在线线免费观看| 亚洲精品中文在线| 欧美成人综合一区| 欧美国产日韩一区二区| 久久激五月天综合精品| 欧美国产第一页| 国产欧美综合在线| 欧美成人精品一区二区| 久久免费高清视频| 欧美一区在线看| 欧美国产日韩精品| 蜜臀av在线播放一区二区三区| 久久综合色婷婷| 欧美激情精品久久久久久| 午夜久久一区| 欧美成人精品在线播放| 亚洲欧洲精品成人久久奇米网 | 久久久久www| 欧美日韩久久| 国产视频一区二区在线观看| 99日韩精品| 日韩写真视频在线观看| 久久综合久久综合这里只有精品| 国产精品爽黄69| 国产精品99久久久久久久vr | 国产精品高清一区二区三区| 国产主播一区二区| 欧美一级日韩一级| 亚洲素人在线| 亚洲精品一区二区三区在线观看| 国产伊人精品| 亚洲激情av| 国产精品日韩电影| 中日韩美女免费视频网站在线观看| 日韩午夜精品视频| 另类av导航| 欧美激情在线播放| 在线观看精品视频| 午夜一区二区三区不卡视频| 一本久久a久久精品亚洲| 久久久精品999| 免费不卡欧美自拍视频| 亚洲第一免费播放区| 欧美在线短视频| 亚洲视频在线观看视频| 99re66热这里只有精品4| 狠狠色香婷婷久久亚洲精品| 欧美亚洲在线播放| 在线亚洲欧美专区二区| 亚洲影院免费观看| 欧美一级久久| 欧美极品在线观看| 亚洲日本理论电影| 在线观看日韩欧美| 亚洲一区国产| 亚洲美女视频在线观看| 老司机午夜精品视频| 亚洲国产mv| 亚洲第一中文字幕| 久久激情久久| 一二三四社区欧美黄| 国产精品都在这里| 亚洲精品看片| 午夜亚洲影视| 亚洲电影免费观看高清完整版| 久久综合亚州| 亚洲一区二区三区激情| 久久精品成人欧美大片古装| 国产精品实拍| 久久天堂av综合合色| 制服丝袜激情欧洲亚洲| 激情综合色综合久久综合| 亚洲视频免费在线观看| 欧美激情中文字幕乱码免费| 日韩视频在线观看| 一区二区av在线| 国产日韩一区在线| 欧美黄色免费网站| 欧美成人资源网| 麻豆精品91| 校园春色国产精品| 久久精品首页| 日韩天堂av| 久久综合精品国产一区二区三区| 国内不卡一区二区三区| 欧美午夜不卡影院在线观看完整版免费 | 一区二区三区视频在线播放| 性欧美长视频| 亚洲欧洲在线看| 欧美午夜一区| 国产欧美日韩精品一区| 欧美11—12娇小xxxx| 亚洲国产日韩在线一区模特| 久久欧美肥婆一二区| 日韩午夜在线视频| 最新日韩av| 国产精品美女在线| 欧美精品在线免费| 蜜臀av在线播放一区二区三区 | 亚洲国产成人91精品 | 在线观看视频免费一区二区三区| 老司机精品导航| 亚洲欧美一区二区原创| 美乳少妇欧美精品| 亚洲欧美日韩系列| 在线观看中文字幕不卡| 欧美日韩国产一区二区| 欧美1区免费| 久久综合狠狠| 美乳少妇欧美精品| 久久九九久久九九| 午夜日韩av| 99天天综合性| 亚洲视频免费看| 亚洲欧美一区二区精品久久久| 夜夜爽www精品| 亚洲欧美一区二区激情| 久久综合狠狠综合久久激情| 国自产拍偷拍福利精品免费一| 尤物九九久久国产精品的特点| 亚洲一区二区三区免费观看| 亚洲欧美资源在线| 在线免费观看日本欧美| 中日韩美女免费视频网址在线观看| 一本不卡影院| 欧美精品一区二区高清在线观看| 免费亚洲电影在线| 国产精品三级久久久久久电影| 国产一区二区三区黄视频| 亚洲桃花岛网站| 亚洲欧洲在线一区| 中国成人在线视频| 欧美人与禽性xxxxx杂性| 性久久久久久久久| 最新国产精品拍自在线播放| 午夜精品亚洲| 欧美日精品一区视频| 亚洲激情视频| 欧美一区二区视频在线观看| 午夜天堂精品久久久久| 一色屋精品视频在线观看网站 | 亚洲精品一二区| 中文久久精品| 久久精品一区蜜桃臀影院| 一本一本a久久| 欧美激情aⅴ一区二区三区| 一区一区视频| 99视频精品在线| 女仆av观看一区| 久久久精品日韩| 亚洲日产国产精品| 亚洲一级黄色片| 欧美日韩精品久久| 1024成人| 久久久人成影片一区二区三区观看 | 99国产欧美久久久精品| 久久香蕉精品| 国产乱理伦片在线观看夜一区| 一区二区三区四区国产| 亚洲精品在线电影| 欧美先锋影音| 欧美一区二区在线看|