簡體   English   中英

有沒有辦法比較兩個不同的C / C ++程序運行?

[英]Is there a way to compare two different runs of a C/C++ program?

所以我正在調試這個程序,這個程序是我從即將畢業的博士生中繼承的,或者是在學生完成論文后發生的任何事情。 無論如何,現在我有責任進行調試。 該程序基本上接受幾個文本文件並處理它們。 我遇到的問題(段錯誤)是因為程序試圖訪問尚未初始化的數組。 我想知道是否有任何調試工具可以讓你運行程序,並比較程序關閉的兩個不同路徑。 我想我可以手動完成程序,但我寧願不這樣做,因為它相當大,我仍然沒有掌握它。 我一直在使用GDB和Valgrind(以及使用g ++ -wall來顯示警告),這就是我如何做到這一點。 但是,是否有任何軟件讓你按照我上面所描述的那樣做,甚至只是讓你完成你的程序。

我認為您正在尋找正確的方向,您可以選擇GDB和valgrind等工具。

使用GDB,您可以在兩種條件下編寫程序的執行腳本,並在發生段錯誤時查看調用堆棧。 然后,您可以在該位置放置一個斷點,並使用不會使程序崩潰的參數再次運行,並調查兩者的差異。

使用valgrind,它實際上是一套工具( http://valgrind.org/info/tools.html ),使用callgrind和kcachegrind可以取得一些成功。 Callgrind為您提供調用圖,kcachegrind( http://kcachegrind.sourceforge.net/cgi-bin/show.cgi/KcacheGrindIndex )允許您對它們進行可視化。 我將它們用於大型C代碼庫的性能分析。

另一個可以幫助你的工具是Fenris( http://lcamt​​uf.coredump.cx/fenris/whatis.shtml ),它也可以打印出代碼的調用圖。 在閱讀您的要求時,我認為Fenris最接近,因為它還允許您“可視化”所采用的代碼路徑。

這些建議特定於GCC。 您可以使用gcov coverage工具詳細說明程序的哪些部分已執行以及執行頻率。 您必須將一些特殊選項傳遞給GCC,以便為gcov生成適當的檢測和輸出。

--coverage此選項用於編譯和鏈接用於覆蓋率分析的代碼。 該選項是-fprofile-arcs -ftest-coverage (編譯時)和-lgcov (鏈接時)的-lgcov 有關更多詳細信息,請參閱這些選項的文檔。

然后,當您執行程序時,會生成一些分析和覆蓋數據。 然后,您可以調用gcov來分析該輸出。 以下是從上面的鏈接獲取的輸出示例:

         -:    0:Source:tmp.c
         -:    0:Graph:tmp.gcno
         -:    0:Data:tmp.gcda
         -:    0:Runs:1
         -:    0:Programs:1
         -:    1:#include <stdio.h>
         -:    2:
         -:    3:int main (void)
         1:    4:{
         1:    5:  int i, total;
         -:    6:
         1:    7:  total = 0;
         -:    8:
        11:    9:  for (i = 0; i < 10; i++)
        10:   10:    total += i;
         -:   11:
         1:   12:  if (total != 45)
     #####:   13:    printf ("Failure\n");
         -:   14:  else
         1:   15:    printf ("Success\n");
         1:   16:  return 0;
         -:   17:}

如果要實現自己的檢測以記錄程序的調用歷史記錄,可以在GCC上使用-finstrument-functions及其相關選項。

-finstrument-functions
生成用於進入和退出函數的檢測調用。 在函數輸入之后和函數退出之前,使用當前函數的地址及其調用站點調用以下分析函數。 (在某些平台上, __builtin_return_address不能在當前函數之外工作,否則調用站點信息可能無法用於分析功能。)

      void __cyg_profile_func_enter (void *this_fn,
                                     void *call_site);
      void __cyg_profile_func_exit  (void *this_fn,
                                     void *call_site);

第一個參數是當前函數的開始地址,可以在符號表中准確查找。

在C ++中,您對這些鈎子的實現應該聲明為extern "C" 每次調用函數時都可以實現鈎子記錄。 您沒有獲取函數名稱,但您可以使用objdumpaddr2line在后面處理指針。

GDB可以讓您逐行“逐步”完成您的程序。 一些技巧:

  1. 只需在main處鍵入(鍵入b main ),然后按n + Enter鍵執行當前行並繼續執行下一行。
  2. 如果要進入該功能,請按s + Enter鍵(即進入被調用的功能並從那里繼續)。
  3. 輸入p +變量名來打印出來的值(非常好判斷該變量是否已初始化,提示提示......)
  4. 如果從命令行運行GDB並想要一個GUI包裝器,請使用Emacs。 只需鍵入emacs program.c ,然后鍵入Alt + x ,然后鍵入gdb 輸入可執行文件的名稱,然后按Enter鍵。 現在您可以看到更多代碼,並仍然使用gdb命令進行調試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM