macos 在 Mac OS X 上获取当前堆栈跟踪
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/289820/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting the current stack trace on Mac OS X
提问by user33847
I'm trying to work out how to store and then print the current stack in my C++ apps on Mac OS X. The main problem seems to be getting dladdr to return the right symbol when given an address inside the main executable. I suspect that the issue is actually a compile option, but I'm not sure.
我正在尝试解决如何在 Mac OS X 上的 C++ 应用程序中存储和打印当前堆栈。主要问题似乎是在给定主可执行文件中的地址时让 dladdr 返回正确的符号。我怀疑这个问题实际上是一个编译选项,但我不确定。
I have tried the backtrace code from Darwin/Leopard but it calls dladdr and has the same issue as my own code calling dladdr.
我已经尝试了来自 Darwin/Leopard 的回溯代码,但它调用了 dladdr,并且与我自己的调用 dladdr 的代码存在相同的问题。
Original post: Currently I'm capturing the stack with this code:
原帖:目前我正在使用以下代码捕获堆栈:
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;
}
Which seems to work ok. Then to print the stack I'm looking at using dladdr like this:
这似乎工作正常。然后打印我正在使用 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);
Which almost works, some example output:
这几乎有效,一些示例输出:
/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]
It's getting the method name right for the shared object but not for the main app. Those just map to "tart" (or "start" minus the first character).
它为共享对象获取了正确的方法名称,但不适用于主应用程序。那些只是映射到“tart”(或“start”减去第一个字符)。
Ideally I'd like line numbers as well as the method name at that point. But I'll settle for the correct function/method name for starters. Maybe shoot for line numbers after that, on Linux I hear you have to write your own parser for a private ELF block that has it's own instruction set. Sounds scary.
理想情况下,我想要行号以及当时的方法名称。但我会为初学者选择正确的函数/方法名称。也许在那之后拍摄行号,在 Linux 上我听说你必须为一个拥有自己指令集的私有 ELF 块编写自己的解析器。听起来很吓人。
Anyway, can anyone sort this code out so it gets the method names right?
无论如何,任何人都可以整理出这段代码,以便获得正确的方法名称吗?
回答by Louis Gerbarg
What releases of OS X are you targetting. If you are running on Mac OS X 10.5 and higher you can just use the backtrace() and backtrace_symbols() libraray calls. They are defined in execinfo.h, and there is a manpagewith some sample code.
您的目标是什么版本的 OS X。如果您在 Mac OS X 10.5 及更高版本上运行,您可以只使用 backtrace() 和 backtrace_symbols() 库调用。它们在 execinfo.h 中定义,并且有一个包含一些示例代码的联机帮助页。
Edit:
编辑:
You mentioned in the comments that you need to run on Tiger. You can probably just include the implementation from Libc in your app. The source is available from Apple's opensource site. Here is a link to the relevent file.
您在评论中提到您需要在 Tiger 上运行。您可能只在您的应用程序中包含来自 Libc 的实现。该源代码可从 Apple 的开源站点获得。这是相关文件的链接。