2008-11-14 31 views
6

Geçerli yığını, Mac OS X'teki C++ uygulamalarında saklamak ve yazdırmak için çalışıyorum. Ana sorun doğru sembolü döndürmek için dladdr almak gibi görünüyor ana çalıştırılabilir içinde bir adres verildiğinde. Sorunun aslında bir derleme seçeneği olduğundan şüpheleniyorum ama emin değilim.Geçerli yığın izini Mac OS X'e getirme

Backtrace kodunu Darwin/Leopard'dan denedim, ancak dladdr'i çağırıyor ve dladdr'i kendi kodumla aynı soruna sahip.

Orijinal Mesaj:

int BackTrace(Addr *buffer, int max_frames) 
{ 
    void **frame = (void **)__builtin_frame_address(0); 
    void **bp = (void **)(*frame); 
    void *ip = frame[1]; 
    int i; 

    for (i = 0; bp && ip && i < max_frames; i++) 
    { 
     *(buffer++) = ip; 
     ip = bp[1]; 
     bp = (void**)(bp[0]); 
    } 

    return i; 
} 

Tamam iş gibi görünüyor: Şu anda bu kodla yığını yakalayan ediyorum. Sağ paylaşılan nesne değil için için

/Users/matthew/Library/Frameworks/Lgi.framework/Versions/A/Lgi+0x2473d(LgiStackTrace+0x5d) [0x102c73d] 
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x2a006(tart+0x28e72) [0x2b006] 
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x2f438(tart+0x2e2a4) [0x30438] 
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x35e9c(tart+0x34d08) [0x36e9c] 
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x1296(tart+0x102) [0x2296] 
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x11bd(tart+0x29) [0x21bd] 

Bu yöntem adı gidiyor: neredeyse, bazı örnek çıktı çalışır

Dl_info dli; 
if (dladdr(Ip, &dli)) 
{ 
    ptrdiff_t  offset; 
    int c = 0; 

    if (dli.dli_fname && dli.dli_fbase) 
    { 
     offset = (ptrdiff_t)Ip - (ptrdiff_t)dli.dli_fbase; 
     c = snprintf(buf, buflen, "%s+0x%x", dli.dli_fname, offset); 
    } 
    if (dli.dli_sname && dli.dli_saddr) 
    { 
     offset = (ptrdiff_t)Ip - (ptrdiff_t)dli.dli_saddr; 
     c += snprintf(buf+c, buflen-c, "(%s+0x%x)", dli.dli_sname, offset); 
    } 

    if (c > 0) 
     snprintf(buf+c, buflen-c, " [%p]", Ip); 

: Sonra böyle dladdr kullanmada Bakıyorum yığını yazdırmak için ana uygulama. Bunlar sadece "tart" (veya ilk karakteri hariç "start") ile eşler.

İdeal olarak, satır numaralarının yanı sıra bu noktada yöntem adını kullanmayı isterim. Ancak, başlangıçlar için doğru işlev/yöntem adını alacağım. Belki de bundan sonra satır numaraları için çekim yapın, Linux'ta kendi komut setine sahip özel bir ELF bloğu için kendi çözümleyicinizi yazmanız gerektiğini duydum. Kulağa korkutucu geliyor.

Her neyse, kimse bu kodu dışarı sıralayabilir, böylece yöntem adlarını doğru alır?

cevap

12

OS X'in hangi sürümlerini hedefliyorsunuz? Mac OS X 10.5 ve üzeri sürümlerde çalışıyorsanız, sadece backtrace() ve backtrace_symbols() kütüphane çağrılarını kullanabilirsiniz. Bunlar execinfo.h dosyasında tanımlanmıştır ve bir örnek kodla birlikte bir manpage vardır.

Düzenleme:

Sen Tiger çalıştırmak için gereken yorum olarak bahsedilen. Uygulamanızdaki uygulamalardan muhtemelen Libc’yi eklemeniz yeterlidir. Kaynak, Apple'ın açık kaynak sitesinden edinilebilir. İşte ilgili file için bir bağlantı.

+0

Şu anda mevcut ve önceki sürümleri, örneğin Leopard ve Tiger'ı hedefliyorum. Ayrıca şu anda Macbook'umda Tiger var. Böylece, kar leopardı çıkana kadar benim kodumun Tiger'da derlenmesi/çalıştırılması gerekecektir. – user33847

+0

Bu işlevin kaynak kodu açık kaynak kodludur, dolayısıyla uygulamayı muhtemelen uygulamanıza dahil edebilirsiniz. Cevabımı ilgili bilgilerle düzenliyorum. –

+0

Bağlantıları gönderdiğiniz kodlara baktım ve sonunda kodumla aynı şekilde dladdr kullanıyor. Hangi aynı yanlış sonuçları verir, benim çalıştırılabilirimdeki (yani paylaşılan bir nesne değil) herhangi bir şeyin "tart" sembolü vardır. – user33847