示例:当调用我的方法-fooBar时,我希望它在控制台中登录其他类所谓的其他方法。
现在,我只知道如何记录fooBar本身及其类的方法名称,其中包含:
_cmd
[self class]
这有可能搞清楚吗?
答案 0 :(得分:35)
在完全优化的代码中,没有100%可靠的方法来确定某个方法的调用者。编译器可以使用尾调用优化,而编译器有效地重用调用者的堆栈帧用于被调用者。
要查看此示例,请使用gdb在任何给定方法上设置断点,然后查看回溯。请注意,在每次方法调用之前都没有看到objc_msgSend()。这是因为objc_msgSend()对每个方法的实现进行尾调用。
虽然您可以编译未优化的应用程序,但您需要所有系统库的非优化版本才能避免这一问题。
这只是一个问题;实际上,你问“我如何重新发明CrashTracer或gdb?”。一个非常难以解决的职业问题。除非你想要“调试工具”成为你的职业,否则我建议不要走这条路。
你真的想回答什么问题?
答案 1 :(得分:6)
this:
怎么样?NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1];
NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:@""];
NSLog(@"Class caller = %@", [array objectAtIndex:3]);
NSLog(@"Method caller = %@", [array objectAtIndex:4]);
原作者intropedro的致谢。
答案 2 :(得分:3)
在没有实际行走堆叠的情况下,一般情况下是不可能的。甚至没有保证另一个对象发送调用该方法的消息。例如,它可以从信号处理程序中的块调用。
答案 3 :(得分:2)
请参阅backtrace(3)。
答案 4 :(得分:2)
使用以下方法
传递要显示方法的索引,如果要显示完整的方法堆栈
+(void) methodAtIndex:(int)index{
void* callstack[128];
int frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
if (index == -1) {
for (int i = 0; i < frames; ++i) {
printf("%s\n", strs[i]);
}
}
else {
if (index < frames) {
printf("%s\n", strs[index]);
}
}
free(strs);
}
答案 5 :(得分:2)
NSLog(@"Show stack trace: %@", [NSThread callStackSymbols]);
答案 6 :(得分:1)
可以使用DTrace
获取此信息。
答案 7 :(得分:1)
创建一个宏,将函数名称__FUNCTION__
添加到函数调用中。然后,该宏将使用char *的额外参数调用您的函数到目标函数。