将NSValue解码为b2fixture时的EXC_BAD_ACCESS
EXC_BAD_ACCESS when decoding NSValue into b2fixture
解决这个问题已经有一段时间了。我使用的是box2D,并将b2fixture编码为NSValue。当我使用解码时出现问题
[value getValue:&fixture];
2012年,这个代码在我的旧mac上运行得很好,但在过去的4年里,矩阵中似乎发生了一些事情!
以下是编码和解码的相关代码:
vertGrid = [[NSMutableArray alloc] initWithCapacity:(NSUInteger) xUnits];
for (int x = 0; x <= xUnits; x++) {
b2Fixture *fixture = ... (not relevant)
NSValue *wrappedValue = [NSValue value:&fixture withObjCType:@encode(struct b2Fixture)];
[vertGrid addObject:wrappedValue];
}
//test I can unwrap the vertGrid
for (NSValue *value in vertGrid) {
b2Fixture *fixture;
[value getValue:&fixture];
NSLog(@"yo yo yo");
}
如果它有效,那么纯属偶然。您没有包装内容,而是意外地复制了指针。内存管理和内存对齐的变化现在可能会"打破"它(32位对64位?)。
无论如何,你的包装和展开都是错误的,因为两者都有额外的(不正确的)间接性。让我们从包装值开始。您的代码是:
b2Fixture *fixture = ... (not relevant)
NSValue *wrappedValue = [NSValue value:&fixture withObjCType:@encode(struct b2Fixture)];
-[NSValue value:withObjCType:]
的文档提供了必要的信息:
value
:指向要存储在新值对象中的数据的指针。
由于您希望存储数据,因此需要传递struct b2Fixture *
,因为该方法将从该内存位置读取数据,但您传递的是struct b2Fixture **
。因此,将复制错误的数据(指针而不是数据)。
这里有另一个关于这种方法实际工作方式的提示:
此方法与
valueWithBytes:objCType:
具有相同的效果,并且可能在将来的版本中被弃用。您应该使用valueWithBytes:objCType:
。
换句话说:方法复制内容,而不是指向内容的指针。方法名称并没有说明这一点,这就是为什么使用valueWithBytes:objCType:
是一个更好的选择。
因此,您包装价值的调用必须是:
NSValue *wrappedValue = [NSValue value:fixture withObjCType:@encode(struct b2Fixture)];
(注意缺少&
)。
接下来,展开。您有:
b2Fixture *fixture;
[value getValue:&fixture];
再次,让我们看看-[NSValue getValue:]
的文档,它说:
buffer
:将值复制到其中的缓冲区。缓冲区必须足够大以容纳值
这意味着您需要分配存储。这里有两种选择:按库存分配或按堆分配。
// Allocate on the stack:
b2Fixture fixture;
[value getValue:&fixture];
// Allocate on the heap:
b2Fixture *fixture = malloc(sizeof(b2Fixture));
[value getValue:fixture]; // No "&"!
...
free(fixture);
评论后更新:
由于您似乎正在尝试包装一个C++对象,因此需要采取不同的做法。我认为有两种方法可以解决这个问题:
- 增强对象,使其提供二进制表示并序列化。添加一个可以反序列化二进制表示的构造函数
- 使用
+[NSValue valueWithPointer:]
和-[NSValue pointerValue]
。这假设对象位于堆上,并将使内存管理更加复杂
- 使用来自 Excel VBA 的 C++ dll 时"Bad DLL calling convention" - 如何解决?
- C++17 编解码器在将标准::字符串转换为标准::字符串时抛出"bad conversion"
- 对于代理容器上的迭代器来说,"least bad implementation"可能是什么?
- 获取错误:在抛出"std::bad::alloc"的实例后终止调用 what(): std::bad_alloc
- 为什么 GetSystemMetrics (SM_CXVIRTUALSCREEN) 返回'bad'值?
- 将 lambda 传递给 STL 集时出错"bad function call"
- 新的 C++14 位分隔符处"Bad Character" Eclipse Oxygen 错误
- 使用 #define 被认为是"bad practice"吗?
- "400 Bad request"使用 OpenSSL BIO 进行请求时
- 解密文件AES_256_CBC返回"bad decrypt"错误
- 在C++流中,eof(),fail(),bad()和good()有什么区别
- make / gcc:"bad build"的可能原因是什么?
- 什么是地址0xbaddc0dedeadbead "Bad decode dead bead"
- 在多线程环境中,什么可能导致"bad file descriptor"?
- "std::vector"在调整大小时引发"bad allocation"异常
- 尝试使用 execp、dup2 和管道实现 shell,挂起或"bad file descriptor"
- OpenCV SVM 在火车上抛出异常,"Bad argument (There is only a single class)"
- 成员函数 bad() 的 std::ftsream 用于检查
- 使用 boost::asio 和 boost::thread 时"Bad file descriptor"
- OpenCV C++神经网络 predict() 函数抛出"Bad argument"错误