简体   繁体   English

程序由于意志力而使调用堆栈溢出

[英]Program overflows call stack by sheer force of will

Here's the call stack from a user's crash report : 是用户崩溃报告中的调用堆栈:

Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   com.growl.GrowlSafari           0x179d383c writeWithFormat + 25
1   com.growl.GrowlSafari           0x179d388e writeWithFormat + 107
2   com.growl.GrowlSafari           0x179d388e writeWithFormat + 107
3   com.growl.GrowlSafari           0x179d388e writeWithFormat + 107
4   com.growl.GrowlSafari           0x179d388e writeWithFormat + 107
5   com.growl.GrowlSafari           0x179d388e writeWithFormat + 107

The trace cuts off at frame 511. 轨迹在帧511处截断。

Here's writeWithFormat : 这是writeWithFormat

int writeWithFormat(FILE *file, NSString *format, ...) {
    va_list args;
    va_start(args, format);
    int written = writeWithFormatAndArgs(file, format, args);
    va_end(args);
    return written;
}

As you can see, it doesn't call itself. 如您所见,它不会自我调用。

Here's the function it does call: 这是它确实调用的函数:

int writeWithFormatAndArgs(FILE *file, NSString *format, va_list args) {
    return 0;
    return fprintf(file, "%s\n", [[[[NSString alloc] initWithFormat:format arguments:args] autorelease] UTF8String]);
}

(As you can guess, this is logging code that's inactivated.) (您可以猜到,这是未激活的日志记录代码。)

So, how does this code result in that stack trace? 那么,此代码如何导致该堆栈跟踪?


Disassembly using otx: 使用otx反汇编:

_writeWithFormatAndArgs:
    +0  00000f68  55                    pushl       %ebp
    +1  00000f69  89e5                  movl        %esp,%ebp
    +3  00000f6b  31c0                  xorl        %eax,%eax
    +5  00000f6d  c9                    leave
    +6  00000f6e  c3                    ret

_writeWithFormat:
    +0  00001823  55                    pushl       %ebp
    +1  00001824  89e5                  movl        %esp,%ebp
    +3  00001826  83ec10                subl        $0x10,%esp
    +6  00001829  31c0                  xorl        %eax,%eax
    +8  0000182b  c9                    leave
    +9  0000182c  c3                    ret

In the full crash report, you can see in the binaries section that the user has two copies of GrowlSafari loaded: 在完整的崩溃报告中,您可以在“二进制文件”部分中看到用户已加载了两个GrowlSafari副本:

 0x140c000 -  0x140efff +com.growl.GrowlSafari 1.1.6 (1.1.6) <1E774BDF-5CC5-4876-7C66-380EBFEAF190> /Library/InputManagers/GrowlSafari/GrowlSafariLoader.bundle/Contents/PlugIns/GrowlSafari.bundle/Contents/MacOS/GrowlSafari
0x179d2000 - 0x179d4ff7 +com.growl.GrowlSafari 1.2.1 (1.2.1) <10F1EF69-D655-CCEE-DF3A-1F6C0CF541D3> /Applications/GrowlSafari.app/Contents/Resources/GrowlSafari.bundle/Contents/MacOS/GrowlSafari

The code I showed in the question is from 1.2.1 (but there's a good chance it hasn't changed since 1.1.6) and the disassembly is of 1.2.1. 我在问题中显示的代码来自1.2.1(但是很有可能自1.1.6起它没有发生变化),反汇编为1.2.1。

This probably is the cause of the problem, especially as the recursion appears to actually be in a swizzled method (thanks to @_karsten_ on Twitter for pointing this out ). 这可能是造成问题的原因,尤其是在递归似乎实际上处于混乱的方法中时(感谢Twitter上的@_karsten_ 指出了这一点 )。

A tail call somewhere in there could be causing one or more functions to disappear from the stack trace which, of course, makes debugging a load of fun. 某个地方的尾部调用可能导致一个或多个函数从堆栈跟踪中消失,这当然使调试变得很有趣。

Off the top of my head, I could think of two possible scenarios that could cause this: 我不由自主地想到了两种可能导致这种情况的情况:

  • the format string is a subclass of NSString or there is a category somewhere that is causing a call through to writeWithFormat() during that writeWithFormat(). 格式字符串是NSString的子类,或者某个地方的某个类别在该writeWithFormat()期间导致对writeWithFormat()的调用。 Custom logging code will do that sometimes -- it is quite frighteningly easy to write some generic custom logging code that'll happily call back into itself. 定制日志记录代码有时会做到这一点-编写一些通用的定制日志记录代码非常容易,这会很容易地回调自身。 Been there, done that. 去过也做过。 Many times, sadly. 可悲的是很多次。

  • a perversity in memory is causing the recursion; 内存中的异常导致递归; corrupted object or something. 损坏的物体或其他东西。

Both a bit of a grasp at straws. 两者都有一点点吸管。 Post the entire crash report. 发布整个崩溃报告。


Two versions of the bundle swizzling the runtime... all bets are off until the crash is reproduced in the face of only one of those bundles. 捆绑软件的两个版本使运行时变得混乱...所有赌注都关闭了,直到仅面对其中一个捆绑软件时才再现崩溃。 I'd bet that is the problem. 我敢打赌这就是问题所在。

I also bet that there is some related console spew. 我也打赌,有一些相关的控制台喷出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM