“ EXC_BREAKPOINT (SIGTRAP)”异常是否由调试断点引起?

我有一个多线程应用程序,它在我所有的测试机器上都非常稳定,而且似乎对我的几乎每一个用户都很稳定(基于没有崩溃的抱怨)。不过,这个应用程序经常因为一个用户而崩溃,这个用户很好心地发送了崩溃报告。所有的崩溃报告(10个连续的报告)看起来基本相同:

Date/Time:       2010-04-06 11:44:56.106 -0700
OS Version:      Mac OS X 10.6.3 (10D573)
Report Version:  6


Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000002, 0x0000000000000000
Crashed Thread:  0  Dispatch queue: com.apple.main-thread


Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   com.apple.CoreFoundation        0x90ab98d4 __CFBasicHashRehash + 3348
1   com.apple.CoreFoundation        0x90adf610 CFBasicHashRemoveValue + 1264
2   com.apple.CoreText              0x94e0069c TCFMutableSet::Intersect(__CFSet const*) const + 126
3   com.apple.CoreText              0x94dfe465 TDescriptorSource::CopyMandatoryMatchableRequest(__CFDictionary const*, __CFSet const*) + 115
4   com.apple.CoreText              0x94dfdda6 TDescriptorSource::CopyDescriptorsForRequest(__CFDictionary const*, __CFSet const*, long (*)(void const*, void const*, void*), void*, unsigned long) const + 40
5   com.apple.CoreText              0x94e00377 TDescriptor::CreateMatchingDescriptors(__CFSet const*, unsigned long) const + 135
6   com.apple.AppKit                0x961f5952 __NSFontFactoryWithName + 904
7   com.apple.AppKit                0x961f54f0 +[NSFont fontWithName:size:] + 39

(... . 更多文字如下)

首先,我花了很长时间研究[ NSFont fontWithName: size: ]。我认为可能是用户的字体不知怎么搞错了,所以[ NSFont fontWithName: size: ]请求了一些不存在的东西,因为这个原因而失败了。我使用[[ NSFontManager sharedFontManager ] ailableFontNamesWithTraits: NSItalicFontMask ]添加了一堆代码,以提前检查字体的可用性。遗憾的是,这些改变并没有解决问题。

现在我注意到我忘记删除一些调试断点,包括 _ NSLockError、[ NSException 集合]和 objecc _ eption _ throw。然而,该应用程序绝对是使用“发布”作为活动构建配置来构建的。我假设使用“发布”配置可以防止设置任何断点——但是,我也不确定断点是如何工作的,或者是否需要从 gdb 内部运行程序来使断点产生任何效果。

我的问题是: 我没有设置断点是否会导致用户观察到的崩溃?如果是这样,为什么断点只会给这个用户带来问题呢?如果没有,是否有其他人在[ NSFont fontWithName: size: ]上遇到过类似的问题?

我可能只是尝试删除断点并将其发送回用户,但我不确定该用户还剩下多少货币。而且我想更一般地了解,离开断点集是否可能导致问题(当应用程序使用“发布”配置构建时)。

88439 次浏览

Breakpoints aren't written to the binary. Odds are good that this person has a broken OS installation. Check the console logs for dyld messages.

It is extremely likely that this user has a corrupt font installed. The stack trace definitely supports that hypothesis, as does the fact that it's only affecting one user.

There's not much you can do in that case except get the user to remove the offending font, as the crashes that occur take place deep down in Apple's code.

Try getting the user to run a font validation in Font Book. To do this, launch Font Book, click All Fonts in the source list and then select all the listed fonts. You can then select Validate Fonts from the File menu.

Are “EXC_BREAKPOINT (SIGTRAP)” exceptions caused by debugging breakpoints?

No. Other way around, actually: A SIGTRAP (trace trap) will cause the debugger to break (interrupt) your program, the same way an actual breakpoint would. But that's because the debugger always breaks on a crash, and a SIGTRAP (like several other signals) is one type of crash.

SIGTRAPs are generally caused by NSExceptions being thrown, but not always—it's even possible to directly raise one yourself.

I've now noticed that I forgot to remove some debugging breakpoints, including _NSLockError, [NSException raise], and objc_exception_throw.

Those are not breakpoints. Two of them are functions and -[NSException raise] is a method.

Did you mean you set breakpoints on those functions and that method?

I assume that using the "Release" configuration prevents setting of any breakpoints--

No.

The configurations are build configurations. They affect how Xcode builds your applications.

Breakpoints are not part of the build; you set them in the debugger. They only exist, only get hit, and only stop your program when you run your program under the debugger.

Since they aren't part of the build, it's not possible to pass your breakpoints to a user simply by giving them the app bundle.

I am not sure exactly how breakpoints work …

When your program hits the breakpoint, the debugger breaks (interrupts) your program, whereupon you can examine the program's state and step carefully forward to see how the program goes wrong.

Since it's the debugger that stops your program, breakpoints have no effect when you're not running your program under the debugger.

… or whether the program needs to be run from within gdb for breakpoints to have any effect.

It does. Debugger breakpoints only work within the debugger.

My questions are: could my having left the breakpoints set be the cause of the crashes observed by the user?

No.

First, as noted, even if these breakpoints did somehow get carried over to the user's system, breakpoints are only effective in the debugger. The debugger can't stop on a breakpoint if your program isn't running under the debugger. The user almost certainly isn't running your app under the debugger, especially since they got a crash log out of it.

Even if they did run your app under the debugger with all of these breakpoints set, a breakpoint is only hit when your program reaches that point, so one of these breakpoints could only fire if you or Cocoa called _NSLockError, -[NSException raise], or objc_exception_throw. Getting to that point wouldn't be the cause of the problem, it'd be a symptom of the problem.

And if you did crash as a result of one of those being called, your crash log would have at least one of them named in it. It doesn't.

So, this wasn't related to your breakpoints (different machine, debugger not involved), and it wasn't a Cocoa exception—as I mentioned, Cocoa exceptions are one cause of SIGTRAPs, but they are not the only one. You encountered a different one.

If not, has anybody else had similar problems with [NSFont fontWithName:size:]?

There's no way we can tell whether any problems we've had are similar because you cut off the crash log. We know nothing about what context the crash happened in.

The only thing that's good to cut out is the “Binary images” section, since we don't have your dSYM bundles, which means we can't use that section to symbolicate the crash log.

You, on the other hand, can. I wrote an app for this purpose; feed the crash log to it, and it should detect the dSYM bundle automatically (you are keeping the dSYM bundle for every Release build you distribute, right?) and restore your function and method names into the stack trace wherever your functions and methods appear.

For further information, see the Xcode Debugging Guide.

I had the same error. For an unexplainable reason the breakpoint was the responsible of the throwing the EXC_BREAKPOINT exception. The solution was to remove the breakpoint, and then code works.

EXC_BREAKPOINT is a type of exception that debuggers use. When you set a breakpoint in your code, the compiler inserts an exception of this type in the executable code. When the execution reaches that point, the exception is thrown and the debugger catches it. Then the debugger shows your code in the "breakpointed" line. This is how debuggers work. But in this case the debugger does not handle the exception correctly and is presented as a regular exception error.

I have found this error two times in my life:

  • one using Xcode about a year ago.
  • the other using Visual C++ about 15 years ago.