2009-08-30 9 views
19

Mi chiedo perché la funzione di valutazione non funzioni in gdb? Nel mio file sorgente includo, durante il debug in gdb, questi esempi sono valutazioni sbagliate.Come valutare le funzioni in GDB?

(gdb) p pow(3,2) 

$10 = 1 

(gdb) p pow(3,3) 

$11 = 1 

(gdb) p sqrt(9) 

$12 = 0 

risposta

14

La mia ipotesi è che il compilatore e il linker facciano un po 'di magia con quelle particolari funzioni. Molto probabilmente per aumentare le prestazioni.

Se è assolutamente necessario pow() ad essere disponibile in gdb allora si può creare il proprio funzione wrapper:

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

Forse anche avvolgerlo in un #ifdef DEBUG o qualcosa di non ingombrare il binario finale.

proposito, si noterà che le altre funzioni di libreria può essere chiamato (e il loro valore di ritorno stampati), per esempio:

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

La risposta corretta è data di seguito da anon – mattypiper

15

La sintassi per chiamare una funzione in gdb è

call pow(3,2) 

Tipo

help call 

al prompt gdb per ulteriori informazioni.

+0

Grazie! Ma chiamata è ancora non funziona correttamente (gdb) chiamata sqrt (9) $ 14 = 0 (gdb) chiamata pow (3,3) $ 15 = 1 – Tim

+1

stampa sarà anche chiamare le funzioni. In effetti, penso che l'unica differenza sia che la chiamata non ingombrerà l'output quando si chiamano le funzioni void –

0
NAME 
    pow, powf, powl - power functions 

SYNOPSIS 
    #include <math.h> 

    double pow(double x, double y); 

Non si dovrebbe passare un int al posto di una doppia

call pow(3. , 2.) 

Inoltre, il superamento di un singolo argomento non è sufficiente a dire, avete bisogno di due argomenti, proprio come la funzione si aspetta

wrong: call pow (3.) 
+1

, in effetti i transiti funzionano bene. non sono sicuro se sia solo una coincidenza, ma chiamare mypow (vedi la mia risposta) con numeri interi produce il risultato corretto. Non ottengo output da gdb quando si chiama pow (2.0.2.0), ma lo faccio quando si chiama mypow() con qualsiasi numero –

4

In realtà, almeno sul mio implementazione Linux di gcc, molte delle funzioni matematiche vengono sostituiti con varianti specifiche per i tipi dei loro argomenti tramite alcune sostituzioni di fantasia introdotte da Math.h e bits/mathcalls.h (incluso all'interno di math.h). Di conseguenza, le funzioni come pow e exp vengono chiamate invece come __pow o *__GI___exp (i risultati possono variare a seconda del tipo di argomenti e, forse, della versione specifica).

Per identificare quale sia esattamente la funzione collegata al mio codice, inserisco un'interruzione in una linea in cui viene chiamata solo quella funzione, ad es. avere una riga nel mio codice con b=exp(c);. Quindi eseguo in gdb fino a quel punto di interruzione e poi uso il comando "step" per inserire la chiamata da quella linea. Quindi posso usare il comando "where" per identificare il nome della routine chiamata. Nel mio caso era *__GI___exp.

Ci sono probabilmente modi più intelligenti per ottenere queste informazioni, tuttavia, non sono stato in grado di trovare il nome giusto solo eseguendo il preprocessore da solo (l'opzione -E) o guardando il codice assembly generato (-s).

+2

So che questo è vecchio, ma se qualcuno viene a cercare, ecco qui: Per me ha funzionato solo con 'p pow' che mi ha dato:' $ 28 = {} 0x7ffff77ffbd0 <__pow> ' – falstro

14

Devi dire a gdb che troverà il valore di ritorno nei registri a virgola mobile, non quelli normali, oltre a dare i parametri ai tipi giusti.

cioè .:

(gdb) p ((doppia (*)()) pow) (2, 2.)

$ 1 = 4

+0

È strano che ottenga un valore di' $ 1 = 2' – daj

2

pow è definito come una macro, non una funzione. La chiamata in gdb può solo chiamare funzioni nel tuo programma o nella libreria condivisa. Quindi, la chiamata a pow in gdb dovrebbe fallire.

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

ecco il codice binario gcc generato pow sorgente chiamata (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 

ecco il gcc generato codice binario di sorgente chiamata 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