2009-08-30 33 views
19

Neden işlev değerlendirme gdb'de çalışmıyor? Kaynak dosyamda gdb'de hata ayıklama yaparken bu örnekler yanlış değerlendirmeler içeriyor.GDB'deki işlevler nasıl değerlendirilir?

(gdb) p pow(3,2) 

$10 = 1 

(gdb) p pow(3,3) 

$11 = 1 

(gdb) p sqrt(9) 

$12 = 0 

cevap

14

Tahminimce derleyici ve linker bu özel işlevlerle biraz sihir yapıyor. Performansı artırma olasılığı yüksektir.

kesinlikle gdb kullanılabilir olmasını pow() gerekiyorsa sonra kendi sarmalayıcı işlevi oluşturabilirsiniz:

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

Belki de son ikili kalabalıklaştırmaz bir #ifdef DEBUG falan içine sarın.

BTW, örneğin, bir kütüphane işlevi çağrılabilir (ve onların geri dönüş değeri baskılı) göreceksiniz:

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

herhangi bir sayı ile mypow() çağırırken yaparım Doğru cevap aşağıda anon – mattypiper

15

gdb bir işlevi çağırmak için sözdizimi fazla bilgi için gdb istemine yazın

help call 

call pow(3,2) 

olduğunu.

+0

Teşekkürler! Ama çağrı yine de doğru zamanda fonksiyonlarını arayacak (gdb) çağrısı sqrt (9) $ 14 = 0 (gdb) çağrısı pow (3,3) $ 15 = 1 – Tim

+1

baskı çalışma değildir. Aslında, tek fark, aslında, void işlevleri –

0
NAME 
    pow, powf, powl - power functions 

SYNOPSIS 
    #include <math.h> 

    double pow(double x, double y); 

Sen fonksiyonu

wrong: call pow (3.) 
beklediğini gibi yeterli değil, iki argümana ihtiyaç tek bir argüman geçerek Ayrıca çift

call pow(3. , 2.) 

yerine bir int geçirmemelisiniz

+1

çağıran aramaların çıktısını vermenin, çıkışların düzgün çalışmaması, çıktının dağılmayacağıdır. Sadece tesadüf olup olmadığından emin değilim, ama tamsayılarla mypow'u (cevabıma bakın) aramak doğru sonucu verir. Ben pow (2.0,2.0) çağrıldığında gdb hiçbir çıktı almıyorum, ama ben –

4

Aslında en azından gcc'nin benim LINUX uygulanmasına ilişkin, matematik işlevlerinin çoğunu math.h ve bits/mathcalls.h (math.h içinde yer alan) tarafından çekilen bazı süslü ikameler yoluyla argümanlarının türlerine özgü varyantlarla değiştirilir. Sonuç olarak, pow ve exp gibi işlevler __pow veya *__GI___exp olarak adlandırılır (sonuçlarınız, argüman türlerine ve belki de belirli sürümlere bağlı olarak değişebilir).

Koduma tam olarak hangi işlevin bağlı olduğunu tanımlamak için, yalnızca bu işlevin çağrıldığı bir satıra ara verdim, ör. b=exp(c); ile kodumda bir satır var. Sonra gdb'yi bu kırılma noktasına kadar çalıştırın ve sonra o adımdan aramaya girmek için "adım" komutunu kullanın. Ardından, adı geçen rutinin adını tanımlamak için "nerede" komutunu kullanabilirim. Benim durumumda *__GI___exp idi.

Bu bilgileri almanın akıllıca yolları vardır, ancak, yalnızca önişlemciyi tek başına (-E seçeneği) çalıştırarak veya oluşturulan (--s) derleme koduna bakarak doğru adı bulamadık.

+2

tarafından verilir Ben biliyorum eski, ama birisi bakmaya gelir, burada gider: Benim için sadece 'p pow' yapmam için çalıştı: '$ 28 = {<' – falstro

14

Gdb'ye parametrelerin doğru türlerini vermenin yanı sıra kayan nokta kayıtlarında normal değerlere değil de dönüş değerini bulacağını söylemeniz gerekir.

yani .:

(gdb) p ((çift (*)()) POW) (2., 2.)

$ 1 = 4

+0

'$ 1 = 2' bir değer elde edersem – daj

2

pow makro, bir işlev olarak tanımlanır. gdb'deki arama sadece programınızdaki veya paylaşılan kitaplıktaki işlevleri çağırabilir. Yani gdb'de gç çağrısı başarısız oldu.

: burada
(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 (şamandıra, şamandıra) pow çağrı kaynağının ikili kodu oluşturulur: burada
(gdb) p pow(3,2) 
    No symbol "pow" in current context. 

kaynak çağrı POW (int, int) gcc üretilen ikili koddur
(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