GDBで関数を評価できないのはなぜですか?私のソースファイルには、gdbでデバッグするときに、これらの例は間違った評価です。
(gdb) p pow(3,2)
$10 = 1
(gdb) p pow(3,3)
$11 = 1
(gdb) p sqrt(9)
$12 = 0
私の推測では、コンパイラとリンカはそれらの特定の関数でいくつかの魔法をします。パフォーマンスを向上させる可能性が最も高い。
pow()
をgdbで使用可能にする必要がある場合は、独自のラッパー関数を作成できます。
double mypow(double a, double b)
{
return pow(a,b);
}
たぶんそれを#ifdef DEBUG
または最終バイナリを乱雑にしないもの。
ところで、あなたは他のライブラリ関数を呼び出すことができることに気付くでしょう(そしてそれらの戻り値が出力される)、例えば:
(gdb) print printf("hello world")
$4 = 11
パラメータに適切な型を与えることに加えて、通常のレジスタではなく浮動小数点レジスタで戻り値を見つけることをgdbに伝える必要があります。
つまり:
(gdb)p((double(*)())pow)(2.、2。)
$ 1 = 4
Gdbで関数を呼び出すための構文は次のとおりです。
call pow(3,2)
タイプ
help call
詳細については、gdbプロンプトで確認してください。
実際、少なくともgccのLINUX実装では、math.hおよびbits/mathcalls.h(math.h内に含まれる)によって取り込まれた派手な置換を介して、数学関数の多くが引数のタイプに固有のバリアントに置き換えられます。 )。結果として、代わりにpowやexpなどの関数が___pow
_または_*__GI___exp
_として呼び出されます(結果は引数のタイプと特定のバージョンによって異なる場合があります)。
私のコードにリンクされている関数が何であるかを正確に識別するために、その関数だけが呼び出される行にブレークを入れます。コードにb=exp(c);
の行があります。次に、そのブレークポイントまでgdbで実行し、「step」コマンドを使用してその行から呼び出しを入力します。次に、「where」コマンドを使用して、呼び出されたルーチンの名前を識別できます。私の場合、それは_*__GI___exp
_でした。
この情報を取得するための賢い方法はおそらくありますが、プリプロセッサを単独で実行する(-Eオプション)か、生成されたアセンブリコードを見る(-s)だけでは正しい名前を見つけることができませんでした。
powは、関数ではなくマクロとして定義されます。 gdbの呼び出しは、プログラムまたは共有ライブラリの関数のみを呼び出すことができます。したがって、gdbでのpowの呼び出しは失敗するはずです。
(gdb) p pow(3,2)
No symbol "pow" in current context.
これは、pow(int、int)を呼び出すソースのgcc生成バイナリコードです。
(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 <printf@plt>
0x400517 <main+35>: leaveq
0x400518 <main+36>: retq
0x400519: nop
0x40051a: nop
0x40051b: nop
0x40051c: nop
0x40051d: nop
以下は、pow(float、float)を呼び出すソースのgcc生成バイナリコードです。
(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 <printf@plt>
0x40051e <main+42>: leaveq
0x40051f <main+43>: retq
NAME
pow, powf, powl - power functions
SYNOPSIS
#include <math.h>
double pow(double x, double y);
Doubleの代わりにintを渡すべきではありません
call pow( 3. , 2. )
また、単一の引数を渡すだけでは不十分です。関数が期待するように2つの引数が必要です。
wrong: call pow ( 3. )