【发布时间】:2009-11-25 00:51:21
【问题描述】:
示例:当我的方法 -fooBar 被调用时,我希望它登录控制台,哪个其他类的哪个其他方法调用了它。
现在,我只知道如何记录 fooBar 本身的方法名称和它的类,用这个:
_cmd
[self class]
这可以解决吗?
【问题讨论】:
标签: objective-c cocoa cocoa-touch
示例:当我的方法 -fooBar 被调用时,我希望它登录控制台,哪个其他类的哪个其他方法调用了它。
现在,我只知道如何记录 fooBar 本身的方法名称和它的类,用这个:
_cmd
[self class]
这可以解决吗?
【问题讨论】:
标签: objective-c cocoa cocoa-touch
在完全优化的代码中,没有 100% 可靠的方法来确定某个方法的调用者。编译器可以使用尾调用优化,而编译器有效地为被调用者重用调用者的堆栈帧。
要查看此示例,请使用 gdb 在任何给定方法上设置断点并查看回溯。请注意,您不会在每次方法调用之前看到 objc_msgSend()。那是因为 objc_msgSend() 对每个方法的实现进行了尾调用。
虽然您可以编译未优化的应用程序,但您需要所有系统库的未优化版本才能避免这一问题。
这只是一个问题;实际上,您是在问“我如何重新发明 CrashTracer 或 gdb?”。一个非常困难的问题,职业生涯是在这个问题上产生的。除非您希望“调试工具”成为您的职业,否则我建议您不要走这条路。
你真正想回答什么问题?
【讨论】:
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。
【讨论】:
在一般情况下,如果不实际遍历堆栈,这是不可能的。甚至不能保证另一个对象会发送调用该方法的消息。例如,可以从信号处理程序中的块调用它。
【讨论】:
【讨论】:
使用以下方法
传递要显示方法的索引,如果要显示方法的完整堆栈,则传递-1
+(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);
}
【讨论】:
error: warning: couldn't get cmd pointer (substituting NULL): no variable named '_cmd' found in this frame
NSLog(@"Show stack trace: %@", [NSThread callStackSymbols]);
【讨论】:
可以使用DTrace获取此信息。
【讨论】:
制作一个宏,将__FUNCTION__ 添加到函数调用的函数名中。然后,此宏将使用 char* 的额外参数调用您的函数到目标函数。
【讨论】:
我试图了解谁、如何以及何时更改窗口的大小并做了一些手工操作:
- (void)logWindowWidth:(NSString *)whoCalls {
NSLog(@"%@", whoCalls);
NSLog(@"self.window.size.width %f", self.window.size.width);
}
-(void)someMethod {
[self logWindowWidth:@"someMethod - before"];
...
[self logWindowWidth:@"someMethod - after"];
}
-(void)anotherMethod {
[self logWindowWidth:@"anotherMethod - before"];
...
[self logWindowWidth:@"anotherMethod - after"];
}
【讨论】: