2012-03-16 100 views
0

我想查看下面的基本程序的代碼流。函數調用的順序C

#include<stdio.h> 
int main() 
{ 
    FILE *fptr = fopen("/mnt/myfilesystem/test.txt", "r"); 
    if(fptr) { 
     printf("open successful\n"); 
     fclose(fptr); 
    } 
    else 
     printf("open failed\n"); 

    return 0; 
} 

我想查看運行此程序時執行的函數調用的完整序列。 我嘗試使用strace的和ptrace的,但他們只列出了系統調用如何可以做到這一點:( 有什麼建議?提前

謝謝!

+4

分析器會告訴你這一點。 – 2012-03-16 23:37:54

+0

除了系統調用外,我看不到其他東西。 – 2012-03-16 23:39:38

+2

您應該編譯更多的警告。你的「關閉」電話沒有任何意義。 – 2012-03-16 23:42:43

回答

3

這聽起來像你想ltrace

+0

ltrace告訴我爲這個程序執行的系統調用,即fopen,puts和fclose。我想看看在fopen裏面調用了什麼函數(..) – Venom 2012-03-17 01:01:04

+0

'fopen','fclose'或'puts'都不是系統調用。 – 2012-03-17 01:27:17

+0

你使用'-S'選項嗎?如果不嘗試使用它。 – havexz 2012-03-17 01:28:17

5

您可以使用gnu profiler gprof

-pg標誌編譯(main.cc):

gcc -pg main.cc -o main

然後執行它(./main)。你的二進制文件會產生一個文件(gmon.out)。然後,你可以通過使用gprof的獲得跟蹤:

gprof main gmon.out

你的榜樣,我得到:

index % time self children called  name 
       0.00 0.00  1/1   __do_global_ctors_aux [9] 
[7]  0.0 0.00 0.00  1   global constructors keyed to main [7] 
       0.00 0.00  1/1   __static_initialization_and_destruction_0(int, int) [8] 
----------------------------------------------- 
       0.00 0.00  1/1   global constructors keyed to main [7] 
[8]  0.0 0.00 0.00  1   __static_initialization_and_destruction_0(int, int) [8] 

這不是很多信息,因爲您的應用程序並不複雜。

如果要跟蹤系統調用,請嘗試strace ./main。輸出很長,你會看到所有的系統調用:

execve("", [""], [/* 26 vars */]) = 0 
brk(0)         = 0x877f000 
access("", F_OK)  = -1 ENOENT 
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7748000 
access("", R_OK)  = -1 ENOENT 
open("", O_RDONLY) = -1 ENOENT 
open("", O_RDONLY) = -1 ENOENT 
stat64("", 0xbfdc4a18) = -1 ENOENT 
open("", O_RDONLY) = -1 ENOENT 
stat64("", {st_mode=S_IFDIR|0755, st_size=6104, ...}) = 0 
open("", O_RDONLY) = -1 ENOENT 
open("", O_RDONLY)  = 3 
.... 
+0

嗨Perreal。這不起作用。我遵循以下步驟: #gcc -pg filetest.c -o filetest #./filetest 這將生成gmon.out文件。然後我運行 #gprof filetest gmon.out 這隻給出應存在於日誌中的字段,但不包含調用序列。 – Venom 2012-03-17 00:52:06

+0

如果您注意到輸出可以表示爲圖形。或者嘗試'strace。/ main'。 – perreal 2012-03-17 01:15:08

2

這不是一個呼叫跟蹤,這已經回答了,但我認爲代碼包含一個錯誤,這可能是爲什麼你問。

close應該fclose,以匹配fopen

close是文件描述符,而不是它是由fopen

+0

感謝您指出輸入錯誤。我仍然在尋找整個通話追蹤。 – Venom 2012-03-17 00:58:00

+0

AFAIK ltrace給出了調用的函數。 fopen不是系統調用,它是一個函數。它可能是'fopen(...「r」)'只是打電話'打開' – gbulmer 2012-03-17 01:46:34

0

返回FILE*你有沒有訪問到Mac,Solaris或FreeBSD機器?

他們都擁有DTrace,並且通過使用適當的提供者,您可以追蹤任何你想要的東西。如果你有這些操作系統的的一個接入到一臺機器,看看使用DTrace的用戶指南(最好找一個可下載的PDF)

這可能給你一個腳本這確實給人程序跟蹤:
http://www.dtracebook.com/index.php/Applications
http://www.brendangregg.com/dtrace.html

+0

我正在運行ubuntu。 – Venom 2012-03-17 08:22:23

0

靜態編譯和反彙編。

0

編譯進行性能分析時,使用-pg,編譯器會自動插入對名爲mcount的函數的調用。此功能由特殊庫提供,並創建所有呼叫的數據庫(包含從地址和到地址以及計數器)。然而,如果你提供你自己的mcount函數(注意而不是編譯啓用分析)!它可以做你喜歡的任何事情。

我沒有測試這一點,我真的不知道該mcount參數是什麼(雖然我敢肯定,它不是太難找出來),但一個樣本實現可能是這樣的:

void mcount (void *to) 
{ 
    void *from = __builtin_return_address(); 
    printf ("call from %p to %p\n", from, to); 
} 

然後,您可以使用addr2line找出哪個函數包含哪個地址。

雖然存在一個問題:它只計算啓用了配置文件編譯的函數,並且此可能不包含C庫函數(如printf)。

但是,如果你的系統確實有一個配置文件中啓用C庫,那麼你就必須非常小心調用函數,則可能會調用mcount,否則你會得到一個無限循環。一種解決方案是直接使用syscalls手動輸出文本,可能是用asm編寫的。另一種解決方案是檢測遞歸調用並返回而不做任何事情,但是在多線程應用程序中甚至在信號處理程序中都會出現問題。