亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

基于c語言中調試工具的用法匯總(不包含gdb)

2020-01-26 16:14:28
字體:
來源:轉載
供稿:網友

是不是只有編譯的時候才知道程序寫了錯誤?有沒有在未編譯的時候就讓機器幫你檢查錯誤的工具呢?
答案是:有!!

splint工具.用一個最簡單的HELLO WORLD來表述:
=====================================

復制代碼 代碼如下:

/*錯誤很明顯*/
#include <stdio.h>

int main(void)
{
   print("hello world/n", s);
   return
}


-----------------------------------------------------
casio$ splint -strict foo.c
Splint 3.1.1 --- 03 Nov 2006

foo.c: (in function main)
foo.c:5:2: Unrecognized identifier: print <-------找到print不是printf
Identifier used in code has not been declared. (Use -unrecog to inhibit
warning)
foo.c:5:25: Unrecognized identifier: s <-------未定義變量s
foo.c:5:2: Statement has no effect (possible undected modification through call
to unconstrained function print): print("hello wor... <---------不存在prinf函數
Statement has no visible effect --- no values are modified. It may modify
something through a call to an unconstrained function. (Use -noeffectuncon to
inhibit warning)
foo.c:7:2: Parse Error. (For help on parse errors, see splint -help <------對應return語法錯誤
parseerrors.)
*** Cannot continue.

=============================================

cxref

cxref程序分析C源代碼并且生成一個交叉引用。他顯示了每一個符號在程序中何處被提到。他使用標記星號的每一個符號定義位置生成一個排序列表,如下所示:

SYMBOL FILE FUNCTION LINE
BASENID prog.c ― *12 *96 124 126 146 156 166
BINSIZE prog.c ― *30 197 198 199 206
BUFMAX prog.c ― *44 45 90
BUFSIZ /usr/include/stdio.h ― *4
EOF /usr/include/stdio.h ― *27
argc prog.c ― 36
prog.c main *37 61 81
argv prog.c ― 36
prog.c main *38 61
calldata prog.c ― *5
prog.c main 64 188
calls prog.c ― *19
prog.c main 54

在作者的機子上,前面的輸入在程序的源碼目錄中使用下面的命令來生成的:

$ cxref *.c *.h

但是實際的語法因為版本的不同而不同。查看我們系統的文檔或是man手冊可以得到更多的信息。

cflow <使用時輸入cflow *.c就可以了.可以馬上搞清除什么函數調用了什么.>

cflow程序會輸出一個函數調用樹,這是一個顯示函數調用關系的圖表。這對于查看程序結構來了解他是如何操作的以及了解對于一個函數有哪些影響是十分有用的。一些版本的cflow可以同時作用于目標文件與源代碼。查看手冊頁我們可以了解更為詳細的操作。

下面是由一個cflow版本(cflow-2.0)所獲得的例子輸出,這個版本的cflow版本是由Marty Leisner維護的,并且可以網上得到。

1 file_ungetc {prcc.c 997}
2 main {prcc.c 70}
3 getopt {}
4 show_all_lists {prcc.c 1070}
5 display_list {prcc.c 1056}
6 printf {}
7 exit {}
8 exit {}
9 usage {prcc.c 59}
10 fprintf {}
11 exit {}

從這個輸出中我們可以看到main函數調用show_all_lists,而show_all_lists調用display_list,display_list本身調用printf。

這個版本cflow的一個選項就是-i,這會生成一個反轉的流程圖。對于每一個函數,cflow列出調用他的其他函數。這聽起來有些復雜,但是實際上并不是這樣。下面是一個例子。

19 display_list {prcc.c 1056}
20 show_all_lists {prcc.c 1070}
21 exit {}
22 main {prcc.c 70}
23 show_all_lists {prcc.c 1070}
24 usage {prcc.c 59}
...
74 printf {}
75 display_list {prcc.c 1056}
76 maketag {prcc.c 487}
77 show_all_lists {prcc.c 1070}
78 main {prcc.c 70}
...
99 usage {prcc.c 59}
100 main {prcc.c 70}

例如,這告訴我們調用exit的函數有main,show_all_lists與usage。

使用prof/gprof執行性能測試

當我們試著追蹤一個程序的性能問題時一個十分有用的技術就是執行性能測試(execution profiling)。通常被特殊的編譯器選項以及輔助程序所支持,一個程序的性能顯示他在哪里花費時間。

prof程序(以及其GNU版本gprof)會由性能測試程序運行時所生成的執行追蹤文件中輸出報告。一個可執行的性能測試是由指定-p選項(對prof)或是-pg選項(對gprof)所生成的:

$ cc -pg -o program program.c

這個程序是使用一個特殊版本的C庫進行鏈接的并且被修改來包含監視代碼。對于不同的系統結果也許不同,但是通常是由安排頻繁被中斷的程序以及記錄執行位置來做到的。監視數據被寫入當前目錄中的一個文件,mon.out(對于gprof為gmon.out)。

$ ./program
$ ls -ls
2 -rw-r--r-- 1 neil users 1294 Feb 4 11:48 gmon.out

然后用命令:gprof ./program可以查看到下面的報告

prof/gprof程序讀取這些監視數據并且生成一個報告。查看其手冊頁可以詳細了解其程序選項。下面以gprof輸出作為一個例子:

cumulative self self total
time seconds seconds calls ms/call ms/call name
18.5 0.10 0.10 8664 0.01 0.03 _doscan [4]
18.5 0.20 0.10 mcount (60)
14.8 0.28 0.08 43320 0.00 0.00 _number [5]
9.3 0.33 0.05 8664 0.01 0.01 _format_arg [6]
7.4 0.37 0.04 112632 0.00 0.00 _ungetc [8]
7.4 0.41 0.04 8757 0.00 0.00 _memccpy [9]
7.4 0.45 0.04 1 40.00 390.02 _main [2]
3.7 0.47 0.02 53 0.38 0.38 _read [12]
3.7 0.49 0.02 w4str [10]
1.9 0.50 0.01 26034 0.00 0.00 _strlen [16]
1.9 0.51 0.01 8664 0.00 0.00 strncmp [17]

內存調試

富含bug而且難于跟蹤調試的一個區域就是動態內存分配。如果我們編譯一個使用malloc與free來分配內存的程序,很重要的一點就是我們要跟蹤我們所分配的內存塊,并且保證不要使用已經釋放的內存塊。

通常,內存是由malloc分配并且賦給一個指針變量的。如果指針變量被修改了,而又沒有其他的指針來指向這個內存塊,他就會變為不可訪問的內存塊。這就是一個內存泄露,而且會使得我們程序尺寸變大。如果我們泄露了大量的內存,那么我們的系統就會變慢并且會最終用盡內存。

如 果我們在超出一個分配的內存塊的結束部分(或是在一個內存塊的開始部分)寫入數據,我們很有可能會破壞malloc庫來跟蹤分配所用的數據結構。在這種情 況下,在將來的某個時刻,調用malloc,或者甚至是free,就會引起段錯誤,而我們的程序就會崩潰。跟蹤錯誤發生的精確點是非常困難的,因為很可能 他在引起崩潰的事件發生以前很一段時間就已經發生了。

不必奇怪的是,有一些工具,商業或是自由的,可以有助于處理這兩種問題類型。例如,有許多不同的malloc與free版本,其中的一些包含額外的代碼在分配與回收上進行檢測嘗試檢測一個內存塊被釋放兩次或是其他一些濫用類型的情況。

ElectricFence

ElectricFence 庫是由Bruce Perens開發的,并且在一些Linux發行版本中作為一個可選的組件來提供,例如RedHat,而且已經可以在網絡上獲得。他嘗試使用Linux的虛 擬內存工具來保護malloc與free所使用的內存,從而在內存被破壞時終止程序。

試驗--ElectricFence

下面的程序,efence.c,使用malloc分配一個內存塊,然后在超出塊結束處寫入數據。讓我們看一下會發生什么情況。

復制代碼 代碼如下:

#include <stdio.h>
#include <stdlib.h>
int main()
{
   char *ptr = (char *) malloc(1024);
   ptr[0] = 0;
   /* Now write beyond the block */
   ptr[1024] = 0;/*寫非法*/
   exit(0);
}

當我們編譯運行這個程序時,我們并不會看到進一步的行為。然而,似乎malloc所分配的內存區域有一些問題,而我們實際上已經遇到了麻煩。

$ cc -o efence efence.c
$ ./efence
$

然而,如果我們使用ElectricFence庫,libefence.a來鏈接這個程序,我們就會得到一個即時的響應。

$ cc -o efence efence.c -lefence
$ ./efence
Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
Segmentation fault
$

在調試器下運行可以定位這個問題:

$ cc -g -o efence efence.c -lefence
$ gdb efence
(gdb) run
Starting program: /home/neil/BLP3/chapter10/efence
[New Thread 1024 (LWP 1869)]
Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1024 (LWP 1869)]
0x080484ad in main () at efence.c:10
10 ptr[1024] = 0;
(gdb)

工作原理

Electric替換malloc并且將函數與計算機處理器的虛擬內存特性相關聯來阻止非法的內存訪問。當這樣的訪問發生時,就會拋出一個段錯誤信息從而可以終止程序。

valgrind

valgrind是一個可以檢測我們已經討論過的許多問題的工具。事實上,他可以檢測數據訪問錯誤與內存泄露。也許他并沒有被包含在我們的Linux發行版本中,但是我們可以在http://developer.kde.org/~sewardj處得到。

程序并不需要使用valgrind重新編譯,而我們甚至可以調用一個正在運行的程序的內存訪問。他很值得一看,他已經用在主要的開發上,包含KDE版本3。

試驗--valgrind

下面的程序,checker.c,分配一些內存,讀取超過那塊內存限制的位置,在其結束處之外寫入數據,然后使其不能訪問。

復制代碼 代碼如下:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
   char *ptr = (char *) malloc(1024);
   char ch;
   /* Uninitialized read */
   ch = ptr[1024];/*讀非法*/
   /* Write beyond the block */
   ptr[1024] = 0;/*寫非法*/
   /* Orphan the block */
   ptr = 0;/*野指針*/
   exit(0);
}

要使用valgrind,我們只需要簡單的運行valgrind命令,傳遞我們希望檢測的選項,其后是使用其參數運行的程序。

當我們使用valgrind來運行我們的程序時,我們可以看到診斷出許多問題:

$ valgrind --leak-check=yes -v ./checker
==3436== valgrind-1.0.4, a memory error detector for x86 GNU/Linux.
==3436== Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.
==3436== Estimated CPU clock rate is 452 MHz
==3436== For more details, rerun with: -v
==3436==
==3436== Invalid read of size 1
==3436== at 0x8048397: main (checker.c:10)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436== Address 0x42AD1424 is 0 bytes after a block of size 1024 alloc'd
==3436== at 0x4003CA75: malloc (vg_clientfuncs.c:100)
==3436== by 0x8048389: main (checker.c:6)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436==
==3436== Invalid write of size 1
==3436== at 0x80483A4: main (checker.c:13)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436== Address 0x42AD1424 is 0 bytes after a block of size 1024 alloc'd
==3436== at 0x4003CA75: malloc (vg_clientfuncs.c:100)
==3436== by 0x8048389: main (checker.c:6)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436==
==3436== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==3436== malloc/free: in use at exit: 1024 bytes in 1 blocks.
==3436== malloc/free: 1 allocs, 0 frees, 1024 bytes allocated.
==3436== For counts of detected errors, rerun with: -v
==3436== searching for pointers to 1 not-freed blocks.
==3436== checked 3468724 bytes.
==3436==
==3436== definitely lost: 1024 bytes in 1 blocks.
==3436== possibly lost: 0 bytes in 0 blocks.
==3436== still reachable: 0 bytes in 0 blocks.
==3436==
==3436== 1024 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3436== at 0x4003CA75: malloc (vg_clientfuncs.c:100)
==3436== by 0x8048389: main (checker.c:6)
==3436== by 0x402574F2: __libc_start_main (in /lib/libc.so.6)
==3436== by 0x80482D1: exit@@GLIBC_2.0 (in /home/neil/BLP3/chapter10/checker)
==3436==
==3436== LEAK SUMMARY:
==3436== definitely lost: 1024 bytes in 1 blocks.
==3436== possibly lost: 0 bytes in 0 blocks.
==3436== still reachable: 0 bytes in 0 blocks.
==3436== Reachable blocks (those to which a pointer was found) are not shown.
==3436== To see them, rerun with: --show-reachable=yes
==3436== $

這里我們可以看到錯誤的讀取與寫入已經被捕獲,而所關注的內存塊與他們被分配的位置相關聯。我們可以使用調試器在出錯點斷開程序。

valgrind 有許多選項,包含特定的錯誤類型表達式與內存泄露檢測。要檢測我們的例子泄露,我們必須使用一個傳遞給valgrind的選項。當程序結束時要檢測內存泄 露,我們需要指定 --leak-check=yes。我們可以使用valgrind --help得到一個選項列表。

工作原理

我們的程序在valgrind的控制下執行,這會檢測我們程序所執行的各種動作,并且執行許多檢測,包括內存訪問。如果程序訪問一個已分配的內存塊并且訪問 是非法的,valgrind就會輸出一條信息。在程序結束時,一個垃圾收集例程就會運行來檢測是否在存在分配的內存塊沒有被釋放。這些孤兒內存也會被報告。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品久久久久久中文字幕大豆网| 国产成+人+综合+亚洲欧洲| 久久青草福利网站| 亚洲国产97在线精品一区| 欧美精品成人91久久久久久久| 久久精品国产精品亚洲| 91chinesevideo永久地址| 日韩美女福利视频| 久久99国产综合精品女同| 亚洲国产精品女人久久久| 欧美国产日本在线| 国产精品香蕉国产| 黑人欧美xxxx| 狠狠做深爱婷婷久久综合一区| 国产欧美最新羞羞视频在线观看| 国产91久久婷婷一区二区| 国产精品久久久久久久久久东京| 国产精品∨欧美精品v日韩精品| 国产99久久精品一区二区永久免费| 隔壁老王国产在线精品| 国产精品一区二区久久久久| 久久精品99久久香蕉国产色戒| 欧美黄色成人网| 午夜精品久久久久久久99热| 亚洲va电影大全| 国产精品女主播视频| 欧美性猛交xxxx乱大交蜜桃| www.欧美三级电影.com| 国产精品三级久久久久久电影| 午夜精品久久久久久久久久久久| 91九色国产视频| 色午夜这里只有精品| 亚洲免费一级电影| 亚洲精品国产精品久久清纯直播| 亚洲最大福利视频网站| 久久久久久亚洲精品中文字幕| 97国产精品久久| 91精品久久久久久久久久久| 热久久这里只有| 国产精品欧美一区二区| 亚洲欧洲激情在线| www.99久久热国产日韩欧美.com| 欧美在线视频观看| 色樱桃影院亚洲精品影院| 国产精品99久久久久久久久久久久| 欧美激情三级免费| 成人免费看吃奶视频网站| 九色成人免费视频| 午夜精品久久久久久99热| 亚洲欧美国产va在线影院| 北条麻妃在线一区二区| 国产在线一区二区三区| 亚洲午夜激情免费视频| 国产精品久久久久久影视| 91av在线不卡| 国产亚洲人成网站在线观看| 欧美老少配视频| 国产精品1区2区在线观看| 欧美日韩加勒比精品一区| 国产精品久久久久久久美男| 国产日产欧美精品| 成人免费网站在线| 欧美日韩国产在线播放| 亚洲精品一区二区三区不| 亚洲男人天堂2024| 最新69国产成人精品视频免费| 国产精品免费福利| 色先锋资源久久综合5566| 91最新在线免费观看| 精品夜色国产国偷在线| 久久久久久欧美| 日韩在线视频导航| 亚洲精品乱码久久久久久金桔影视| 国产三级精品网站| 国产精品一区二区久久久久| 九九热这里只有在线精品视| 中文字幕欧美日韩va免费视频| 欧美高清理论片| 国产精品久久久久久久久影视| 一区二区三区视频免费在线观看| 亚洲白虎美女被爆操| 午夜精品免费视频| 中文字幕欧美精品日韩中文字幕| 亚洲高清av在线| 日韩国产精品亚洲а∨天堂免| 国产精品久久久久高潮| 日韩大陆欧美高清视频区| 91精品视频观看| 国产精品男女猛烈高潮激情| 欧美日韩激情视频| 992tv成人免费影院| 欧美一级视频一区二区| 亚洲天堂男人天堂| 91精品一区二区| 欧美亚洲成人精品| 日本免费久久高清视频| 亚洲精品自拍视频| 91青草视频久久| 国产精品视频久久久久| 97在线视频精品| 亚洲精品日韩在线| 精品国产91久久久久久| 3344国产精品免费看| 国产高清视频一区三区| 久久亚洲精品成人| 亚洲精品久久久久国产| 久久久久久久久久婷婷| 日韩欧美福利视频| 亚洲一区av在线播放| 992tv在线成人免费观看| 欧美极品少妇与黑人| 欧美日韩xxxxx| 久久国内精品一国内精品| 久久久久女教师免费一区| 成人久久一区二区| 成人福利视频在线观看| 日本国产精品视频| 久久免费视频这里只有精品| 欧美丝袜第一区| 97久久国产精品| 成人日韩av在线| 亚洲国产高清福利视频| 午夜精品久久久久久久白皮肤| 国产精品午夜国产小视频| 在线精品播放av| 深夜福利一区二区| 国产精品高潮呻吟久久av黑人| 国产成人精品在线视频| 日韩少妇与小伙激情| 久久伊人精品天天| 国产在线观看91精品一区| 成人在线免费观看视视频| 中文字幕国产亚洲2019| 精品中文字幕久久久久久| 国产精品一区二区久久国产| 亚洲欧洲成视频免费观看| 国产精品久久久久91| 96国产粉嫩美女| 国产成人短视频| 色香阁99久久精品久久久| 久久久女人电视剧免费播放下载| 久久色精品视频| 亚洲人成啪啪网站| 日本高清视频精品| 久久久精品视频在线观看| 91久久久亚洲精品| 日韩精品在线免费观看视频| 国产日韩精品在线| 尤物九九久久国产精品的分类| 亚洲国产精品久久91精品| 日韩美女视频免费看| 欧美猛交ⅹxxx乱大交视频| 国产成人涩涩涩视频在线观看| 一区二区成人av| 毛片精品免费在线观看| 亚洲a级在线播放观看| 久久综合伊人77777蜜臀| 色偷偷av亚洲男人的天堂| 91超碰中文字幕久久精品| 日韩中文字幕在线播放| 国产91精品高潮白浆喷水| 中文.日本.精品| 亚洲精品98久久久久久中文字幕| 91在线网站视频|