2009-08-30 24 views
19

Zastanawiam się, dlaczego funkcja oceny nie działa w gdb? W moim pliku źródłowym uwzględniam, podczas debugowania w gdb, te przykłady są błędnymi ocenami.Jak oceniać funkcje w GDB?

(gdb) p pow(3,2) 

$10 = 1 

(gdb) p pow(3,3) 

$11 = 1 

(gdb) p sqrt(9) 

$12 = 0 

Odpowiedz

14

Domyślam się, że kompilator i linker działają trochę magicznie z tymi konkretnymi funkcjami. Najprawdopodobniej zwiększy wydajność.

Jeśli koniecznie trzeba pow() być dostępne w gdb wówczas można stworzyć własną funkcję Wrapper:

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

Może również zawinąć go w #ifdef DEBUG lub czegoś nie zaśmiecać ostateczną binarny.

BTW, można zauważyć, że inne funkcje biblioteczne można nazwać (a ich wartość zwracana drukowane), na przykład:

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

Poprawna odpowiedź jest podana poniżej przez anon – mattypiper

15

Składnia wywołania funkcji w gdb jest

call pow(3,2) 

Rodzaj

help call 

w wierszu gdb aby uzyskać więcej informacji.

+0

Dzięki! Ale połączenie jest nadal nie działa poprawnie (gdb) wywołanie sqrt (9) $ 14 = 0 (gdb) pow połączeń (3,3) $ 15 = 1 – Tim

+1

Funkcje drukowania będzie również zadzwonić. W rzeczywistości, myślę, że jedyną różnicą jest to, że wywołanie nie będzie zaśmiecać wyjścia podczas wywoływania funkcji void –

0
NAME 
    pow, powf, powl - power functions 

SYNOPSIS 
    #include <math.h> 

    double pow(double x, double y); 

Nie należy zdać int w miejscu podwójnego

call pow(3. , 2.) 

Ponadto, przekazując jeden argument nie wystarczy, potrzebne są dwa argumenty, podobnie jak funkcja oczekuje

wrong: call pow (3.) 
+1

w rzeczywistości, przekazując ints działa dobrze. nie jestem pewien, czy to tylko zbieg okoliczności, ale wywołanie mypow (zobacz moją odpowiedź) z liczbami całkowitymi daje prawidłowy wynik. Nie otrzymuję wyjścia z gdb podczas wywoływania pow (2.0,2.0), ale robię to podczas wywoływania mypow() z dowolnymi numerami –

4

Faktycznie, przynajmniej na moim wdrażania Linuksa gcc, wiele funkcji matematycznych są zamieniane na warianty specyficzne dla typów ich argumentów za pomocą jakichś wymyślnych substytutów wciągniętych przez math.h i bitów/mathcalls.h (zawartych w matematyce.h). W konsekwencji funkcje takie jak pow i exp są nazywane jako __pow lub *__GI___exp (twoje wyniki mogą się różnić w zależności od typów argumentów i być może konkretnej wersji).

Aby określić, która funkcja jest powiązana z moim kodem, wstawiam przerwę w linii, w której wywoływana jest tylko ta funkcja, np. mieć linię w moim kodzie z b=exp(c);. Następnie uruchamiam gdb do tego punktu przerwania, a następnie używam polecenia "krok", aby wprowadzić połączenie z tej linii. Następnie mogę użyć polecenia "where", aby zidentyfikować nazwę wywoływanej procedury. W moim przypadku było to *__GI___exp.

Prawdopodobnie istnieją sprytniejsze sposoby uzyskania tych informacji, jednak nie udało mi się znaleźć właściwej nazwy, uruchamiając sam preprocesor (opcja -E) lub patrząc na wygenerowany kod (-s) zespołu.

+2

Wiem, że to jest stare, ale jeśli ktoś przyjdzie na wygląd, oto: Dla mnie działało to po prostu na 'p pow', które dało mi:' $ 28 = {} 0x7ffff77ffbd0 <__pow> ' – falstro

14

Musisz poinformować gdb, że znajdzie on wartość zwracaną w rejestrach zmiennoprzecinkowych, a nie normalnych, a ponadto poda parametry odpowiednie typy.

tj .:

(gdb) p ((podwójna (*)()) POW) (2, 2.)

$ 1 = 4

+0

To dziwne, że otrzymuję wartość' $ 1 = 2' – daj

2

pow jest zdefiniowana jako makro, a nie funkcji. Połączenie w gdb może wywoływać tylko funkcje w twoim programie lub w bibliotece współdzielonej. Tak więc wywołanie funkcji pow w gdb powinno zakończyć się niepowodzeniem.

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

tutaj jest gcc wygenerowany kod binarny źródła nazywając 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 

tutaj jest gcc wygenerowany kod binarny źródła nazywając Pow (float, float):

(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