評価関数がgdbで機能しないのはなぜですか?私のソースファイルには、gdbでデバッグする際に、これらの例が間違った評価となっています。GDBで関数を評価するには?
(gdb) p pow(3,2)
$10 = 1
(gdb) p pow(3,3)
$11 = 1
(gdb) p sqrt(9)
$12 = 0
評価関数がgdbで機能しないのはなぜですか?私のソースファイルには、gdbでデバッグする際に、これらの例が間違った評価となっています。GDBで関数を評価するには?
(gdb) p pow(3,2)
$10 = 1
(gdb) p pow(3,3)
$11 = 1
(gdb) p sqrt(9)
$12 = 0
私の推測では、コンパイラとリンカは、それらの特定の機能でいくつかの魔法をしていると思います。パフォーマンスを向上させる可能性が最も高い
あなたは絶対に、あなたがあなた自身のラッパー関数を作成することができ、GDBで利用できるようにするpow()
が必要な場合:
double mypow(double a, double b)
{
return pow(a,b);
}
たぶんまた#ifdef DEBUG
または最終バイナリを乱雑にしないように何かにそれを包みます。
ところで、あなたは、例えば、他のライブラリ関数を呼び出すことができます(とその戻り値が印刷された)ことがわかります:
(gdb) print printf("hello world")
$4 = 11
にgdbで関数を呼び出すための構文は、より多くの情報のためのgdbプロンプトで
help call
call pow(3,2)
です。
ありがとうございます!しかし、コールは正常にも機能を呼び出します (GDB)コールSQRT(9) $ = 14 0 (GDB)コールPOW(3,3) $ = 15 1 – Tim
印刷作業ではありません。実際には、唯一の違いは、void関数を呼び出すときにコールが出力を乱雑にしないということです。実際には、intsを正常に渡して –
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型を渡すべきではありません
を渡します。それがちょうど偶然であるかどうかは分かりませんが、整数でmypow(私の答えを見てください)を呼び出すと正しい結果が得られます。私はpow(2.0,2.0)を呼び出すときにgdbからの出力は得られませんが、任意の数値でmypow()を呼び出すとします。 –
実際には、少なくともGCCの私のLinuxの実装で、数学関数の多くmath.hとbits/mathcalls.h(math.hからインクルードされています)によって取り込まれたいくつかの派手な代入によって、引数の型に固有の変形に置き換えられています。結果として、powやexpのような関数が代わりに__pow
または*__GI___exp
と呼ばれます(結果は引数の種類や特定のバージョンによって異なる場合があります)。
私のコードにリンクされている機能が正確に何であるかを特定するために、その関数だけが呼び出された行に改行を入れます。私のコードにb=exp(c);
という行があります。その後、そのブレークポイントまでgdbを実行し、 "step"コマンドを使ってその行から呼び出しを入力します。次に、 "where"コマンドを使用して呼び出されたルーチンの名前を特定できます。私の場合は*__GI___exp
でした。
この情報を取得するにはもっときれいな方法がありますが、プリプロセッサを単独で実行する(-Eオプション)か、生成されたアセンブリコード(-s)を調べるだけで正しい名前を見つけることができませんでした。
で与えられます。これは古いですが、 '$ 28 = {<テキスト変数、デバッグ情報>} 0x7ffff77ffbd0 <__pow>' – falstro
gdbには、浮動小数点レジスタの戻り値が見つかるだろうということを伝える必要があります。
すなわち:
(GDB)P((二重(*)())POW)(2、2。)
$ 1 = 4
これは奇妙なことですが、 '$ 1 = 2'の値が得られます。 – daj
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
正しい答えはanon – mattypiper