2009-08-30 7 views
19

評価関数がgdbで機能しないのはなぜですか?私のソースファイルには、gdbでデバッグする際に、これらの例が間違った評価となっています。GDBで関数を評価するには?

(gdb) p pow(3,2) 

$10 = 1 

(gdb) p pow(3,3) 

$11 = 1 

(gdb) p sqrt(9) 

$12 = 0 

答えて

14

私の推測では、コンパイラとリンカは、それらの特定の機能でいくつかの魔法をしていると思います。パフォーマンスを向上させる可能性が最も高い

あなたは絶対に、あなたがあなた自身のラッパー関数を作成することができ、GDBで利用できるようにするpow()が必要な場合:

double mypow(double a, double b) 
{ 
    return pow(a,b); 
} 

たぶんまた#ifdef DEBUGまたは最終バイナリを乱雑にしないように何かにそれを包みます。

ところで、あなたは、例えば、他のライブラリ関数を呼び出すことができます(とその戻り値が印刷された)ことがわかります:

(gdb) print printf("hello world") 
$4 = 11 
+0

正しい答えはanon – mattypiper

15

にgdbで関数を呼び出すための構文は、より多くの情報のためのgdbプロンプトで

help call 

call pow(3,2) 

です。

+0

ありがとうございます!しかし、コールは正常にも機能を呼び出します (GDB)コールSQRT(9) $ = 14 0 (GDB)コールPOW(3,3) $ = 15 1 – Tim

+1

印刷作業ではありません。実際には、唯一の違いは、void関数を呼び出すときにコールが出力を乱雑にしないということです。実際には、intsを正常に渡して –

0
NAME 
    pow, powf, powl - power functions 

SYNOPSIS 
    #include <math.h> 

    double pow(double x, double y); 

あなたは関数が

wrong: call pow (3.) 
を期待と同じように十分ではない、あなたは二つの引数を必要としている単一の引数を渡し、また、ダブル

call pow(3. , 2.) 

の代わりにint型を渡すべきではありません

+1

を渡します。それがちょうど偶然であるかどうかは分かりませんが、整数でmypow(私の答えを見てください)を呼び出すと正しい結果が得られます。私はpow(2.0,2.0)を呼び出すときにgdbからの出力は得られませんが、任意の数値でmypow()を呼び出すとします。 –

4

実際には、少なくともGCCの私のLinuxの実装で、数学関数の多くmath.hとbits/mathcalls.h(math.hからインクルードされています)によって取り込まれたいくつかの派手な代入によって、引数の型に固有の変形に置き換えられています。結果として、powやexpのような関数が代わりに__powまたは*__GI___expと呼ばれます(結果は引数の種類や特定のバージョンによって異なる場合があります)。

私のコードにリンクされている機能が正確に何であるかを特定するために、その関数だけが呼び出された行に改行を入れます。私のコードにb=exp(c);という行があります。その後、そのブレークポイントまでgdbを実行し、 "step"コマンドを使ってその行から呼び出しを入力します。次に、 "where"コマンドを使用して呼び出されたルーチンの名前を特定できます。私の場合は*__GI___expでした。

この情報を取得するにはもっときれいな方法がありますが、プリプロセッサを単独で実行する(-Eオプション)か、生成されたアセンブリコード(-s)を調べるだけで正しい名前を見つけることができませんでした。

+2

で与えられます。これは古いですが、 '$ 28 = {<テキスト変数、デバッグ情報>} 0x7ffff77ffbd0 <__pow>' – falstro

14

gdbには、浮動小数点レジスタの戻り値が見つかるだろうということを伝える必要があります。

すなわち:

(GDB)P((二重(*)())POW)(2、2。)

$ 1 = 4

+0

これは奇妙なことですが、 '$ 1 = 2'の値が得られます。 – daj

2

POWは、マクロではなく関数として定義されます。 gdbの呼び出しは、プログラム内または共有ライブラリ内の関数のみを呼び出すことができます。だから、gdbのpowへの呼び出しは失敗するはずです。ここで

(gdb) p pow(3,2) 
    No symbol "pow" in current context. 

はgccがPOW(INT、INT)を呼び出すソースのバイナリコードが生成される。

:ここで

(gdb) list 
    1  int main() { 
    2  int a=pow(3,2); 
    3  printf("hello:%d\n", a); 
    4  } 
    (gdb) x/16i main 
    0x4004f4 <main>:  push %rbp 
    0x4004f5 <main+1>: mov %rsp,%rbp 
    0x4004f8 <main+4>: sub $0x10,%rsp 
    0x4004fc <main+8>: movl $0x9,-0x4(%rbp) 
    => 0x400503 <main+15>: mov -0x4(%rbp),%eax 
    0x400506 <main+18>: mov %eax,%esi 
    0x400508 <main+20>: mov $0x40060c,%edi 
    0x40050d <main+25>: mov $0x0,%eax 
    0x400512 <main+30>: callq 0x4003f0 <[email protected]> 
    0x400517 <main+35>: leaveq 
    0x400518 <main+36>: retq 
    0x400519: nop 
    0x40051a: nop 
    0x40051b: nop 
    0x40051c: nop 
    0x40051d: nop 

は、GCCは(フロート、フロート)POWを呼び出し元のバイナリコードが生成されます

(gdb) list 
    1  int main() { 
    2  double a=pow(0.3, 0.2); 
    3  printf("hello:%f\n", a); 
    4  } 
    (gdb) x/16i main 
    0x4004f4 <main>:  push %rbp 
    0x4004f5 <main+1>: mov %rsp,%rbp 
    0x4004f8 <main+4>: sub $0x10,%rsp 
    0x4004fc <main+8>: movabs $0x3fe926eff16629a5,%rax 
    0x400506 <main+18>: mov %rax,-0x8(%rbp) 
    0x40050a <main+22>: movsd -0x8(%rbp),%xmm0 
    0x40050f <main+27>: mov $0x40060c,%edi 
    0x400514 <main+32>: mov $0x1,%eax 
    0x400519 <main+37>: callq 0x4003f0 <[email protected]> 
    0x40051e <main+42>: leaveq 
    0x40051f <main+43>: retq