是调试断点导致的“EXC_BREAKPOINT (SIGTRAP)”异常吗?
Posted
技术标签:
【中文标题】是调试断点导致的“EXC_BREAKPOINT (SIGTRAP)”异常吗?【英文标题】:Are "EXC_BREAKPOINT (SIGTRAP)" exceptions caused by debugging breakpoints? 【发布时间】:2011-02-06 09:13:24 【问题描述】:我有一个多线程应用程序,它在我的所有测试机器上都非常稳定,并且对于我的几乎每个用户来说似乎都是稳定的(基于没有崩溃的投诉)。但是,该应用程序经常为一位用户崩溃,该用户非常好心地发送崩溃报告。所有崩溃报告(约 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] availableFontNamesWithTraits:NSItalicFontMask] 添加了一堆代码来提前检查字体的可用性。遗憾的是,这些更改并没有解决问题。
我现在注意到我忘记删除一些调试断点,包括 _NSLockError、[NSException raise] 和 objc_exception_throw。但是,该应用程序肯定是使用“发布”作为活动构建配置构建的。我假设使用“Release”配置可以防止设置任何断点——但我又不确定断点是如何工作的,或者是否需要从 gdb 中运行程序才能使断点产生任何影响。
我的问题是:我设置的断点是否会导致用户观察到崩溃?如果是这样,为什么断点只会对这个用户造成问题?如果没有,还有其他人对 [NSFont fontWithName:size:] 有类似的问题吗?
我可能会尝试删除断点并将其发回给用户,但我不确定该用户还剩下多少货币。而且我想更一般地了解保留断点设置是否可能会导致问题(当应用程序是使用“发布”配置构建时)。
【问题讨论】:
【参考方案1】:“EXC_BREAKPOINT (SIGTRAP)”异常是调试断点引起的吗?
没有。反过来,实际上:SIGTRAP(跟踪陷阱)将导致调试器中断(中断)您的程序,就像实际断点一样。但这是因为调试器总是在崩溃时中断,而 SIGTRAP(与其他几个 signals 一样)是一种崩溃类型。
SIGTRAPs 通常是由抛出 NSExceptions 引起的,但并非总是如此——甚至可以自己直接raise。
我现在注意到我忘记删除一些调试断点,包括 _NSLockError、[NSException raise] 和 objc_exception_throw。
那些不是断点。其中两个是函数,-[NSException raise]
是一个方法。
你的意思是你在那些函数和那个方法上设置断点?
我假设使用“Release”配置可以防止设置任何断点--
没有。
配置是 build 配置。它们会影响 Xcode 构建应用程序的方式。
断点不是构建的一部分;你在调试器中设置它们。它们只存在,只会被命中,并且只会在您在调试器下运行程序时停止您的程序。
由于它们不是构建的一部分,因此无法仅通过为用户提供应用程序包来将断点传递给用户。
我不确定断点是如何工作的……
当您的程序遇到断点时,调试器会中断(中断)您的程序,然后您可以检查程序的状态并仔细查看程序是如何出错的。
由于停止程序的是调试器,所以当您不在调试器下运行程序时,断点不起作用。
…或者是否需要从 gdb 中运行程序才能使断点生效。
确实如此。调试器断点仅在调试器内起作用。
我的问题是:我设置的断点是否会导致用户观察到崩溃?
没有。
首先,如前所述,即使这些断点确实以某种方式转移到用户系统,断点也仅在调试器中有效。如果您的程序不在调试器下运行,则调试器无法在断点处停止。用户几乎可以肯定没有在调试器下运行您的应用,尤其是因为他们从中得到了崩溃日志。
即使他们确实在设置了所有这些断点的调试器下运行了您的应用程序,也只会在您的程序到达该点时才会触发断点,因此只有当您或 Cocoa 调用 _NSLockError
、@ 时才会触发这些断点之一987654327@,或objc_exception_throw
。到达那一点不会是问题的原因,而是问题的症状。
如果您确实因为其中一个被调用而崩溃,您的崩溃日志中至少会包含其中一个被命名的。没有。
所以,这与您的断点无关(不同的机器,不涉及调试器),也不是 Cocoa 异常——正如我所提到的,Cocoa 异常是 SIGTRAP 的原因之一,但它们不是唯一的.你遇到了一个不同的人。
如果没有,还有其他人对 [NSFont fontWithName:size:] 有类似的问题吗?
我们无法判断我们遇到的任何问题是否相似,因为您切断了崩溃日志。我们对崩溃发生的背景一无所知。
唯一最好删除的是“二进制图像”部分,因为我们没有您的 dSYM 包,这意味着我们不能使用该部分来表示崩溃日志。
另一方面,你可以。为此我写了an app;将崩溃日志提供给它,它应该自动检测 dSYM 包(您为您分发的每个 Release 构建保留 dSYM 包,对吗?)并将您的函数和方法名称恢复到堆栈跟踪中,无论您的函数和方法出现在哪里。
有关详细信息,请参阅Xcode Debugging Guide。
【讨论】:
哇,感谢您的全面回答。 • “你的意思是你在那些函数上设置断点......” 是的,这就是我的意思。 • “断点不是构建的一部分......它们只存在,只会被命中,并且只有在您在调试器下运行程序时才会停止您的程序” 谢谢,这正是我想知道的。 • “象征崩溃日志...我为此目的编写了一个应用程序” 不错的应用程序。我通常通过纯粹的直觉来“象征”——但你的应用程序是一种更好的方式! • 我得出的结论是,这一定是用户字体存在某种问题,并且会从这个角度解决问题。【参考方案2】:该用户极有可能安装了损坏的字体。堆栈跟踪肯定支持该假设,它仅影响一个用户这一事实也是如此。
在这种情况下,除了让用户删除有问题的字体之外,您无能为力,因为发生的崩溃发生在 Apple 代码的深处。
尝试让用户在 Font Book 中运行字体验证。为此,请启动 Font Book,单击源列表中的 All Fonts,然后选择所有列出的字体。然后,您可以从 文件 菜单中选择 Validate Fonts。
【讨论】:
感谢您提供有关字体书的提示——我对字体知之甚少,实际上验证我自己的字体很有趣...我建议用户尝试一下。【参考方案3】:我有同样的错误。由于无法解释的原因,断点是引发 EXC_BREAKPOINT 异常的原因。解决办法是去掉断点,然后代码就可以工作了。
EXC_BREAKPOINT 是调试器使用的一种异常。当您在代码中设置断点时,编译器会在可执行代码中插入此类型的异常。当执行到达那个点时,异常被抛出并且调试器捕获它。然后调试器在“断点”行中显示您的代码。这就是调试器的工作方式。但在这种情况下,调试器无法正确处理异常,并显示为常规异常错误。
我一生中发现过两次这个错误:
大约一年前使用 Xcode。 另一个大约 15 年前使用 Visual C++。【讨论】:
奇怪的是,我得到了这个错误,根本没有任何断点。 我不知道这个错误只发生在断点上:EXC_BREAKPOINT 可能有多种原因发生。我要解释的是一对非常罕见的情况,其中断点会生成未处理的异常。【参考方案4】:断点不会写入二进制文件。这个人的操作系统安装损坏的可能性很大。检查控制台日志以获取 dyld 消息。
【讨论】:
感谢您的快速答复!在谷歌搜索这个问题时,我注意到其他人有与 dyld 消息相关联的 EXC_BREAKPOINTS——但我的崩溃日志没有显示来自 dyld 的任何消息。以上是关于是调试断点导致的“EXC_BREAKPOINT (SIGTRAP)”异常吗?的主要内容,如果未能解决你的问题,请参考以下文章
VS Code 调试器中的 Jest + Babel 导致断点移动