2008-11-14 53 views
6

我正試圖解決如何存儲並在Mac OS X上的C++應用程序中打印當前堆棧。主要問題似乎是讓dladdr返回正確的符號當在主可執行文件中給出一個地址時。我懷疑這個問題實際上是一個編譯選項,但我不確定。在Mac OS X上獲取當前堆棧跟蹤

我已經嘗試了Darwin/Leopard的backtrace代碼,但它調用dladdr並與我自己的代碼調用dladdr時遇到同樣的問題。

原帖: 目前我捕捉與此代碼堆棧:這似乎工作確定

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; 
} 

。然後打印我期待堆棧的使用提供dladdr這樣的:

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); 

幾乎工作,一些示例輸出:

/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] 

它變得方法名稱權的共享對象,但不主要的應用程序。那些只映射到「撻」(或「開始」減去第一個字符)。

理想情況下,我希望行號以及當時的方法名稱。但我會爲初學者解決正確的功能/方法名稱。也許拍攝行號後,在Linux上,我聽說你必須爲擁有自己的指令集的私有ELF塊編寫自己的解析器。聽起來很可怕。

無論如何,任何人都可以將此代碼排序,因此它獲得的方法名稱正確嗎?

回答

12

什麼版本的OS X是你的目標。如果您在Mac OS X 10.5及更高版本上運行,則可以使用backtrace()和backtrace_symbols()libraray調用。它們在execinfo.h中定義,並且有一個manpage帶有一些示例代碼。

編輯:

您在評論中提到您需要在Tiger上運行。你可能只需在你的應用中包含來自Libc的實現。該源可從Apple的開源網站獲得。這是一個鏈接到相關file

+0

我目前正在瞄準當前和以前的版本,即豹和老虎。此外,我目前在我的Macbook上擁有Tiger。因此,直到雪豹出來,我的代碼將需要在Tiger上編譯/運行。 – user33847 2008-11-14 21:50:02