NSLog 实际上做了什么?
我有一个奇怪的问题。我在我的应用程序中使用 Apple 私有框架中的方法。当我第一次调用它时,它起作用了。当我立即第二次调用它而中间没有任何内容时,它崩溃了。但是,如果我将 NSLog 放在两个调用之间,效果会非常好。所以我尝试删除 NSLog 并在它们之间放置 for 循环、sleep()、printf("...") 和 fprintf(stderr, "...") 来模拟 NSLog,但这没有帮助。我想知道该方法如何知道我使用 NSLog?换句话说,NSLog 实际上做了什么来影响方法的行为?
非常感谢!
编辑:
我似乎解决了这个问题。我将在这里分享我的解决方案,希望它对某些人有用。
我正在使用 MultitouchSupport.framework 创建一个与多点触控相关的应用程序。我从 http://aladino.dmi.unict.it/?a=multitouch< 复制了代码/a> 并在循环末尾添加了 CFRelease
。所以,基本上,我的主要方法如下所示:
int main(void) {
int i;
NSMutableArray* deviceList = (NSMutableArray*)MTDeviceCreateList(); //grab our device list
for(i = 0; i<[deviceList count]; i++) { //iterate available devices
MTRegisterContactFrameCallback([deviceList objectAtIndex:i], touchCallback); //assign callback for device
MTDeviceStart([deviceList objectAtIndex:i], 0); //start sending events
}
CFRelease((CFMutableArrayRef)deviceList);
printf("Ctrl-C to abort\n");
sleep(-1);
return 0;
}
运行一段时间后,它将显示“程序收到信号:“EXC_BAD_ACCESS”。 这是堆栈跟踪:
#0 0x7fff8795496e in ParsedMultitouchFrameRepInitialize
#1 0x7fff879565b1 in mt_HandleMultitouchFrame
#2 0x7fff87955a03 in mt_DequeueDataFromDriver
#3 0x7fff87955b29 in mt_DequeueMultitouchDataFromDriverThreadEntry
#4 0x7fff831b3456 in _pthread_start
#5 0x7fff831b3309 in thread_start
但是,如果我将 NSLog 放在 MTDeviceStart 下面,它就不会崩溃。
我在原始代码中添加 CFRelease((CFMutableArrayRef)deviceList)
的原因是我认为从名为 *Create* 或 *Copy* 的函数创建的对象应该由我们自己释放。但事实证明,如果我像原始代码一样删除它,即使不使用 NSLog,它也不会崩溃。
那么,也许是因为我太早发布了 deviceList
?但如果是这样的话,为什么 NSLog 似乎能够防止崩溃呢?
I am having a weird problem. I am using a method from Apple's private frameworks in my application. When I call it for the first time, it works. When I call it for the second time immediately without anything in between, it crashes. However, if I put NSLog between the two calls, it works wonderfully. So I try removing NSLog and puting for-loops, sleep(), printf("..."), and fprintf(stderr, "...") between them to emulate NSLog, but it doesn't help. I am wondering how the method knows that I use NSLog? In other words, what does NSLog actually do to affect the behaviors of the method?
Thank you very much!
EDIT:
I seem to solve this problem. I will share my solution here and hope it may be useful to some people.
I am creating a multitouch-related application using MultitouchSupport.framework. I copied code from http://aladino.dmi.unict.it/?a=multitouch and added a CFRelease
at the end of the loop. So, basically, my main method looks like this :
int main(void) {
int i;
NSMutableArray* deviceList = (NSMutableArray*)MTDeviceCreateList(); //grab our device list
for(i = 0; i<[deviceList count]; i++) { //iterate available devices
MTRegisterContactFrameCallback([deviceList objectAtIndex:i], touchCallback); //assign callback for device
MTDeviceStart([deviceList objectAtIndex:i], 0); //start sending events
}
CFRelease((CFMutableArrayRef)deviceList);
printf("Ctrl-C to abort\n");
sleep(-1);
return 0;
}
After running for a while, it will show "Program received signal: “EXC_BAD_ACCESS”."
And here is the stack trace:
#0 0x7fff8795496e in ParsedMultitouchFrameRepInitialize
#1 0x7fff879565b1 in mt_HandleMultitouchFrame
#2 0x7fff87955a03 in mt_DequeueDataFromDriver
#3 0x7fff87955b29 in mt_DequeueMultitouchDataFromDriverThreadEntry
#4 0x7fff831b3456 in _pthread_start
#5 0x7fff831b3309 in thread_start
However, if I put NSLog below MTDeviceStart, it will not crash.
The reason I added CFRelease((CFMutableArrayRef)deviceList)
to the original code is that I think objects that are created from functions named *Create* or *Copy* should be released by ourselves. But it turns out that if I remove it like the original code does, it will not crash, even without using NSLog.
So, maybe it's because I release deviceList
too early? But if that's so, why does NSLog seem to be able to prevent the crash?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
与此类似的东西:
感谢您提出这个问题,哈哈,我想重写它,以便我可以添加调试变量,这意味着我可以在需要时关闭所有 NSLogging 调用。
Something similar to this:
Thanks for asking this question lol, I wanted to rewrite it so I could add debugging variables, meaning I could turn all NSLogging calls off when needed..
这需要很长时间。我不知道为什么。它打印日期/时间、进程名称、进程 ID、线程 ID 和(最后)您要求的字符串。我认为它还会将日志消息发送到 syslogd(Xcode 或 iPCU 的控制台将多行 NSLogs 显示为单个条目;我忘了是哪个); IPC 可能很重要。
尝试使用 syslog()(
#import
,然后使用syslog(LOG_INFO, "Hello there!");
,如果它有效但没有输出,尝试更改优先级(请参阅man 3 syslog
)。It takes a long time. I'm not sure why. It prints the date/time, process name, process ID, thread ID, and (finally) the string you asked for. I think it also sends the log message to syslogd (either Xcode or iPCU's console shows multiline NSLogs as a single entry; I forget which); the IPC there might be significant.
Try using syslog() (
#import <syslog.h>
and thensyslog(LOG_INFO, "Hello there!");
, if it works but you get no output, try changing the priority (seeman 3 syslog
).NSLog 可能会影响您遇到的问题,因为它会影响线程执行的顺序,因为当您在后台线程中调用 NSLog 时,它必须获得对 stdout 的独占访问权。由于这个原因, printf 调试线程的棘手问题通常会导致“heisenbugs”(即,当您尝试检查它们时,它们会改变行为)。
NSLog can affect issues like the one you are running into because it affects the order that threads execute because when you call NSLog in a background thread, it has to gain exclusive access to stdout. printf debugging tricky problems with threads often leads to "heisenbugs" for this reason (i.e. they change behavior when you try to examine them).
这可能是内存管理的问题:可能是一个无关的释放。如果您发布回溯,可能会对追踪问题有所帮助。 (事实证明,我关注的推特上有人昨晚提到了类似的事情)。
It could be a problem with memory management: an extraneous release perhaps. If you post the traceback, it might be some help in tracking down the issue. (As it turns out, someone on Twitter I follow mentioned something like this last night).