异常代码“ EXC_I386_GPFLT”的含义是什么?

异常代码 EXC_I386_GPFLT的含义是什么?

它的含义是否因情况而异?

在这种情况下,我指的是异常类型 EXC_BAD_ACCESS和异常代码 EXC_I386_GPFLT

该程序是在 Xcode 5.0.1中开发的,处理 BLAS 库的 cblas_zgemm()

非常感谢!

119793 次浏览

您通常可以从头文件中获得信息,例如:

$ cd /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
$ find usr -name \*.h -exec fgrep -l EXC_I386_GPFLT {} \;
usr/include/mach/i386/exception.h
^C
$ more usr/include/mach/i386/exception.h
....
#define EXC_I386_GPFLT          13      /* general protection fault     */

好吧,这是一个普通的保护故障(顾名思义)。在谷歌上搜索“ i386通用保护故障”会得到很多结果,但这个 看起来很有趣:

内存保护也使用段描述符实现。 首先,处理器检查一个值是否加载到一个段中 寄存器引用一个有效的描述符。然后它检查每个 计算的线性地址实际上位于段内 对象检查访问类型(读、写或执行) 段描述符里的信息 如果失败,则引发异常(中断)13(十六进制0D) 称为一般保护故障(GPF)。

13与我们在头文件中看到的匹配,所以看起来是一样的。然而,从应用程序程序员的角度来看,这仅仅意味着我们引用了不应该引用的内存,并且它在硬件上是如何实现的并不重要。

EXC _ I386 _ GPFLT 肯定指的是“一般保护错误”,这是 x86告诉你“你做了一些你不允许做的事情”的方式。这通常并不意味着访问超出了内存范围,但可能是您的代码超出了范围,导致错误的代码/数据以某种方式被使用,从而导致某种类型的保护违规。

不幸的是,如果没有更多的背景信息,很难确切地找出问题所在。在我的 AMD64程序员手册(2005年第二卷)中列出了27种不同的原因——所有人都认为,8年后可能还会有更多的原因。

如果它是一个64位系统,一个看似合理的场景是你的代码使用了一个“非规范指针”——这意味着一个64位地址是这样形成的: 地址的上16位并不全是下48位顶部的副本(换句话说,地址的上16位应该全是0或全是1,基于略低于16位的位)。这个规则是为了保证体系结构能够“安全地扩展地址范围内的有效位数”。这将表明代码要么用其他内容覆盖某些指针数据,要么在读取某些指针值时出界。

另一个可能的原因是 SSE 寄存器的不对齐访问——换句话说,从一个没有16字节对齐的地址读取16字节的 SSE 寄存器。

正如我所说,还有许多其他可能的原因,但大多数都涉及到“正常”代码在32位或64位操作系统中不会做的事情(例如加载带有无效选择器索引的段寄存器或写入 MSR (模型特定的寄存器))。

调试和查找源代码: 启用僵尸应用程序(产品方案)和启动仪器,选择僵尸。 在 Xcode 运行你的应用程序 然后去仪器开始录音。 返回到应用程序并尝试生成错误。 如果有错误调用(对僵尸) ,则应该检测这种错误调用。

希望能有帮助!

我想知道为什么在我的单元测试中会出现这种情况。

我已经在一个包含 throws的协议中添加了一个方法声明; 但是潜在的抛出方法甚至没有在那个特定的测试中使用。在测试中启用僵尸听起来太麻烦了。

事实证明,一次彻底的清理就能解决问题。当那样解决实际问题的时候,我总是惊呆了。

在我的例子中,这个错误是在 Xcode iOS 模拟器上运行应用程序时抛出的。虽然我不能回答具体的问题“什么错误意味着”,我可以说什么帮助我,也许它也帮助别人。

对我来说,解决方案是在模拟器中使用 Erase All Content and Settings,在 Xcode 使用 Clean Build Folder...

这种情况发生在我身上是因为 Xcode 似乎不喜欢我在两个不同的类中使用相同的变量名(如果这很重要的话,那么它们遵循相同的协议,尽管变量名在任何协议中都没有任何关联)。我只是简单地重命名了我的新变量。

在调试的时候,我不得不进入 setter 崩溃的地方才能看到它。这个答案适用于 iOS

我在 Swift 4.2也有过类似的例外。我花了大约半个小时试图在我的代码中找到一个 bug,但是在关闭 Xcode 并删除派生数据文件夹之后,问题已经解决了。这里有一条捷径:

rm -rf ~/Library/Developer/Xcode/DerivedData

如果错误被抛出到将 self定义为 unowned的闭包中,您可能会受到访问内容的限制,并且在某些情况下会得到这个错误代码。尤其是在调试的时候。如果是这种情况,请尝试将 [unowned self]改为 [weak self]

我在做这个的时候得到了这个错误:

 NSMutableDictionary *aDictionary=[[NSMutableDictionary alloc] initWithObjectsAndKeys:<#(nonnull id), ...#>, nil]; //with 17 objects and keys

当我回到:

NSMutableDictionary *aDictionary=[[NSMutableDictionary alloc] init];
[aDictionary setObject:object1 forKey:@"Key1"]; //17 times

我在离开一个视图时遇到了这个问题(跳回到前一个视图)。

原因是

addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
view.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
view.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
view.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor)
])

safeAreaLayoutGuide改为 self可以解决这个问题。

意思是将视图与管理视图的前导、尾随、顶部、底部对齐,而不是到达安全区域)

对于我来说,这个问题与情节串连板有关,可以选择 ViewController build For set iOS 9.0,以及之前为 iOS 10.0和更高版本设置的版本。实际上我想把版本从10降级到 iOS 9.3。

我在 Xcode 12.0 Beta 6(仅在 iOS 14模拟器上)的旋转崩溃中看到了这个错误代码。但是它不会在我真正运行 iOS13的设备上崩溃!因此,如果你正在运行测试版,并在模拟器中看到旋转崩溃,也许你只需要在一个真正的设备上运行非测试版 iOS 版本。

我可以得到这个错误与 UnsafeMutablePointer工作

let ptr = rawptr.assumingMemoryBound(to: A.self) //<-- wrong A.self Change it to B.Self
ptr.pointee = B()

在我的例子中,EXC_I386_GPFLT是由于属性 getter 中缺少返回值而引起的,如下所示:

- (CppStructure)cppStructure
{
CppStructure data;
data.a = self.alpha;
data.b = self.beta;


return data; // this line was missing
}

Xcode 12.2

我的问题是愚蠢的 Xcode Playground。对我来说,这个游乐场自从几年前问世以来就一直不稳定,苹果公司一团糟。

删除派生数据等没有帮助,唯一的方法,使我的代码不抛出是运行它在一个应用程序项目

我在 Swift/iOS 上看到了同样的错误。 在我的例子中,这是因为我试图通过直接使用它的 start()函数来启动 (NS)Operation。但是我需要做的是把它传递给 OperationQueue。像这样的 var queue = OperationQueue(); queue.addOperation(myOperation)

老问题了,没什么 Objective-C 的东西被问到所以我会把我的硬币扔进去,也许能帮到别人。

有典型的 EXC _ BAD _ ACCESS,并与究竟是什么引起它挣扎。

经过深思熟虑,我发现这是由于我的代码引用了块内部的一个变量,这个变量是在块外定义的,并且没有使用 _ _ block 前缀。引用的变量被传递给块中的方法调用,并被引用和定义为一个自动释放参数。

很难用语言来解释。因此,一个 example = code 用于删除我使用块枚举的数组中的客户。“ error”被传入。然后我将它传递给块中调用的方法。在方法调用中更改错误参数的值。然后我尝试在块之外引用它。然后我就得到了错误的访问权限。这些问题和 OP 的问题没有什么关系,但是盯着这个问题让我看到了这个页面,其他人可能会发现这个问题很有用。

- (BOOL)deleteCustomer:(CHCustomer *)customer
error:(NSError *__autoreleasing*)error {


__block BOOL success = YES;
NSMutableArray *customerOrders = [self ordersForCustomer:customer
error:error];
if ([customerOrders count] > 0) {
[customerOrders enumerateObjectsUsingBlock:^(id obj,
NSUInteger idx,
BOOL *stop) {
        

CHOrderHeader *orderHeader = (CHOrderHeader *)obj;
if (![self deleteOrderForOohSeqNo:[orderHeader oohSeqNo]
preserveExistingPhotoKeys:NO
error:error]) {
            

*stop = YES;
success = NO;
}
}]; // enumerateObjectsUsingBlock
}


// EXC_BAD_ACCESS occurred on line below:
NSLog(@"Is this an NSError? %@", [*error class]);


return success;


}

在我的例子中,我没有在 String.localizedStringWithFormatformat参数中使用正确的占位符:

let format = "I have an %s."
let string = "exception"
String.localizedStringWithFormat(format, string)

%s改为 %@解决了这个问题。