2012-03-16 11 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

プロファイラがこれを伝えます。 –

+0

私はシステムコール以外の多くを見ることはできません。 –

+2

さらに多くの警告でコンパイルする必要があります。あなたの 'close'呼び出しは意味をなさない。 –

答えて

3

あなたがltraceをしたいようですね。

+0

ltraceはこのプログラムに対して実行されたシステムコール、つまりfopen、puts、およびfcloseを返します。私はfopen(..)の中でどの関数が呼び出されたのか見たいです。 – Venom

+0

'fopen'や' fclose'や 'puts'はシステムコールではありません。 –

+0

あなたは '-S'オプションを使用していますか?使用しない場合は試してみてください。 – havexz

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。これは動作していません。これは、のgmon.outファイルが生成さ #gccの-pg filetest.c -oファイルテスト # ./filetest:私はこれらの手順に従いました。その後、私はgpr​​ofのファイルテストのgmon.out これが唯一の呼び出しシーケンスをログに存在するはずのフィールドを与えるが、ない #実行します。 – Venom

+0

あなたが気付いた場合、出力はグラフとして表すことができます。または 'strace。/ main'を試してみてください。 – perreal

2

これが回答されているコールトレース、に関するものではありませんが、私はコードはあなたが求めている理由かもしれバグが含まれていることを考えます。

closeは、fopen

closeは、ファイルディスクリプタのためであるfopen

+0

入力ミスを指摘してくれてありがとう。私はまだ全体のコールトレースを探しています。 – Venom

+0

AFAIK ltraceは、呼び出される関数を提供します。 fopenはシステムコールではなく、関数です。 'fopen(..." r ")'単に 'open'を呼び出します – gbulmer

0

によって返されるFILE*にない一致させるために、fcloseする必要がありますは、Mac、SolarisまたはFreeBSDのマシンにアクセスすることがありますか?

これらはすべてDTraceを備えており、適切なプロバイダを使用することで、必要なものをほとんどトレースすることができます。あなたは、これらのOSのいずれかでマシンへのアクセス権を持つDTraceユーザーガイドを見て(好ましくダウンロードPDFファイルを見つける。)

場合、これはあなたのプログラムのトレースを与えないスクリプトを与えるかもしれない:
http://www.dtracebook.com/index.php/Applications
または http://www.brendangregg.com/dtrace.html

+0

私はubuntuを実行しています。 – Venom

0

静的にコンパイルして逆アセンブルします。

0

-pgを使用してプロファイリングのためにコンパイルすると、コンパイラはmcountという名前の関数への呼び出しを自動的に挿入します。この関数は特別なライブラリによって提供され、すべての呼び出し(from-addressとto-address、およびカウンタを持つ)のデータベースを作成します。

しかし、独自のmcount関数を提供している場合(ではなく、はプロファイリングを有効にしてコンパイルするように注意してください)、好きなようにすることができます。

私はこれをテストしていませんでした、と私は本当にMCOUNTパラメータは(私は確信しているものの、それが見つけるためにあまりにも難しいことではありません)が、サンプルの実装は次のようになりますされているのか分からない:

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

あなたは、その後どのようなアドレスが含まれていますどのような機能を把握するaddr2lineを使用することができます。

プロファイリングを有効にしてコンパイルされた関数のみがカウントされ、このはおそらくにprintfなどのCライブラリ関数は含まれていません。お使いのシステムがプロファイル有効にCライブラリを持っている場合

しかし、あなたはその後、mcountを呼ぶかもしれない、あるいはそうでないあなたが無限ループを取得します非常に慎重に呼び出し元の関数である必要があります。 1つの解決策は、直接asmで書かれたsyscallを使用してテキストを手動で出力することです。別の解決策は、再帰呼び出しを検出して何もせずに戻ることですが、それはマルチスレッドアプリケーションやシグナルハンドラでさえ問題になります。

関連する問題