将NSValue解码为b2fixture时的EXC_BAD_ACCESS

时间:2016-04-03 10:09:01

标签: c++ objective-c xcode macos box2d

一直在解决这个问题。我使用box2D并将b2fixture编码为NSValue。使用

解码时会出现问题
[value getValue:&fixture];

这段代码在我的旧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");
}

1 个答案:

答案 0 :(得分:1)

如果它正在运作,那么纯粹的机会。你不小心复制指针,而不是包装内容。内存管理和内存对齐的变化现在可能会“破坏”它(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];

再次,让我们看看documentation of -[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 ++对象,因此您需要采用不同的方式。我有两种解决方法: