最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2013年05月14日 17:49:56   作者:  
本篇文章是對c語言中調(diào)試工具的用法進行了匯總,需要的朋友參考下

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

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

復(fù)制代碼 代碼如下:

/*錯誤很明顯*/
#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函數(shù)
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 <------對應(yīng)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

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

cflow <使用時輸入cflow *.c就可以了.可以馬上搞清除什么函數(shù)調(diào)用了什么.>

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

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

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函數(shù)調(diào)用show_all_lists,而show_all_lists調(diào)用display_list,display_list本身調(diào)用printf。

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

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}

例如,這告訴我們調(diào)用exit的函數(shù)有main,show_all_lists與usage。

使用prof/gprof執(zhí)行性能測試

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

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

$ cc -pg -o program program.c

這個程序是使用一個特殊版本的C庫進行鏈接的并且被修改來包含監(jiān)視代碼。對于不同的系統(tǒng)結(jié)果也許不同,但是通常是由安排頻繁被中斷的程序以及記錄執(zhí)行位置來做到的。監(jiān)視數(shù)據(jù)被寫入當前目錄中的一個文件,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程序讀取這些監(jiān)視數(shù)據(jù)并且生成一個報告。查看其手冊頁可以詳細了解其程序選項。下面以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]

內(nèi)存調(diào)試

富含bug而且難于跟蹤調(diào)試的一個區(qū)域就是動態(tài)內(nèi)存分配。如果我們編譯一個使用malloc與free來分配內(nèi)存的程序,很重要的一點就是我們要跟蹤我們所分配的內(nèi)存塊,并且保證不要使用已經(jīng)釋放的內(nèi)存塊。

通常,內(nèi)存是由malloc分配并且賦給一個指針變量的。如果指針變量被修改了,而又沒有其他的指針來指向這個內(nèi)存塊,他就會變?yōu)椴豢稍L問的內(nèi)存塊。這就是一個內(nèi)存泄露,而且會使得我們程序尺寸變大。如果我們泄露了大量的內(nèi)存,那么我們的系統(tǒng)就會變慢并且會最終用盡內(nèi)存。

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

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

ElectricFence

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

試驗--ElectricFence

下面的程序,efence.c,使用malloc分配一個內(nèi)存塊,然后在超出塊結(jié)束處寫入數(shù)據(jù)。讓我們看一下會發(fā)生什么情況。

復(fù)制代碼 代碼如下:

#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所分配的內(nèi)存區(qū)域有一些問題,而我們實際上已經(jīng)遇到了麻煩。

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

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

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

在調(diào)試器下運行可以定位這個問題:

$ 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并且將函數(shù)與計算機處理器的虛擬內(nèi)存特性相關(guān)聯(lián)來阻止非法的內(nèi)存訪問。當這樣的訪問發(fā)生時,就會拋出一個段錯誤信息從而可以終止程序。

valgrind

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

程序并不需要使用valgrind重新編譯,而我們甚至可以調(diào)用一個正在運行的程序的內(nèi)存訪問。他很值得一看,他已經(jīng)用在主要的開發(fā)上,包含KDE版本3。

試驗--valgrind

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

復(fù)制代碼 代碼如下:

#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命令,傳遞我們希望檢測的選項,其后是使用其參數(shù)運行的程序。

當我們使用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== $

這里我們可以看到錯誤的讀取與寫入已經(jīng)被捕獲,而所關(guān)注的內(nèi)存塊與他們被分配的位置相關(guān)聯(lián)。我們可以使用調(diào)試器在出錯點斷開程序。

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

工作原理

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

相關(guān)文章

  • 一個win32窗口創(chuàng)建示例

    一個win32窗口創(chuàng)建示例

    這篇文章主要介紹了一個win32窗口創(chuàng)建示例,需要的朋友可以參考下
    2014-04-04
  • c語言內(nèi)存泄露示例解析

    c語言內(nèi)存泄露示例解析

    從1988年著名的莫里斯蠕蟲 攻擊到有關(guān) Flash Player 和其他關(guān)鍵的零售級程序的最新安全警報都與緩沖區(qū)溢出有關(guān):“大多數(shù)計算機安全漏洞都是緩沖區(qū)溢出”,Rodney Bates 在 2004 年寫道
    2013-09-09
  • C++實現(xiàn)轉(zhuǎn)置矩陣的循環(huán)

    C++實現(xiàn)轉(zhuǎn)置矩陣的循環(huán)

    大家好,本篇文章主要講的是C++實現(xiàn)轉(zhuǎn)置矩陣的循環(huán),感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • C++中HTTP?代理服務(wù)器的設(shè)計與實現(xiàn)詳解

    C++中HTTP?代理服務(wù)器的設(shè)計與實現(xiàn)詳解

    代理服務(wù)器,即允許一個網(wǎng)絡(luò)終端(一般為客戶端)通過這個服務(wù)與另一?個網(wǎng)絡(luò)終端(一般為服務(wù)器)進行非直接的連接,下面我們就來看看如何使用C++設(shè)計與實現(xiàn)一個HTTP?代理服務(wù)器吧
    2024-01-01
  • C語言單鏈表遍歷與求和示例解讀

    C語言單鏈表遍歷與求和示例解讀

    我們在學習編程的過程中,雖然有些語法很簡單,但是我們還是要做多題。不做題是發(fā)現(xiàn)不了問題的,發(fā)現(xiàn)問題我們就可以“對癥下藥”,進行查漏補缺了。刷題可以先從簡單題開始刷,熟練之后再做一些可以提升自己能力的題
    2022-07-07
  • C語言中find_package()的搜索路徑的實現(xiàn)

    C語言中find_package()的搜索路徑的實現(xiàn)

    本文主要介紹了C語言中find_package()的搜索路徑的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • C語言中system()函數(shù)的用法總結(jié)

    C語言中system()函數(shù)的用法總結(jié)

    system()函數(shù)功能強大。以下小編就為大家介紹一下在C語言中system()函數(shù)的用法。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-10-10
  • c語言for、while和do-while循環(huán)之間的區(qū)別

    c語言for、while和do-while循環(huán)之間的區(qū)別

    大家好,本篇文章主要講的是c語言for、while和do-while循環(huán)之間的區(qū)別,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • VC程序設(shè)計小技巧20例

    VC程序設(shè)計小技巧20例

    這篇文章主要介紹了VC程序設(shè)計小技巧20例,需要的朋友可以參考下
    2014-07-07
  • c++利用vector創(chuàng)建二維數(shù)組的幾種方法總結(jié)

    c++利用vector創(chuàng)建二維數(shù)組的幾種方法總結(jié)

    這篇文章主要介紹了c++利用vector創(chuàng)建二維數(shù)組的幾種方法總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評論

竹北市| 栾城县| 凤山市| 呈贡县| 南木林县| 湖南省| 长海县| 广水市| 剑川县| 本溪市| 海晏县| 夹江县| 榕江县| 漠河县| 区。| 永州市| 苏尼特左旗| 扶余县| 赞皇县| 平果县| 汉川市| 应城市| 淳化县| 南充市| 肥乡县| 顺昌县| 囊谦县| 天台县| 保靖县| 明星| 吴旗县| 绵阳市| 手游| 高安市| 晴隆县| 松桃| 福泉市| 玉门市| 阜平县| 云安县| 新昌县|