2008-11-14 55 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