我花了一些时间来调试这个问题而且我很难过。
我正在尝试将自定义对象紧密地打包到NSData
中,以便在将它们保存到磁盘时节省空间。我已经为这些自定义对象实现了自定义编码和解码方法。当我打包并解压缩对象时,根据调试器正确初始化所有内容。代码运行后,它立即有EXC_BAD_ACCESS code=1
或code=2
。
这是编码和解码:
-(instancetype) initWithData:(NSData *)data {
self = [super init];
if (self) {
_memConstants = [[DWMemoryConstants alloc]init];
int arraySize = _memConstants.chunkSize * _memConstants.chunkSize;
NSData* unencodedBlocks[arraySize];
[data getBytes:unencodedBlocks];
_blocks = [[NSMutableDictionary alloc]init];
for (int i = 0; i < 10; i++) {
DWBlock *block = [[DWBlock alloc]initWithData:unencodedBlocks[i]];
[_blocks setObject:block forKey:[NSValue valueWithCGPoint:CGPointFromString(block.blockName)]];
if (i == 0) {
_position = CGPointFromString(block.chunkName);
}
}
_chunkName = NSStringFromCGPoint(_position);
_bounds = CGRectMake(_position.x * _memConstants.chunkSize * kBlockSpriteWidth,
_position.y * _memConstants.chunkSize * kBlockSpriteWidth,
_memConstants.chunkSize * kBlockSpriteWidth,
_memConstants.chunkSize * kBlockSpriteWidth);
}
return self;
}
-(NSData *) customEncode {
NSMutableData *data = [[NSMutableData alloc]init];
NSData* blocks[_blocks.allValues.count];
int count = 0;
for (DWBlock *block in _blocks.allValues) {
blocks[count] = [block customEncode];
count++;
}
[data appendBytes:&blocks length:sizeof(blocks)];
return data;
}
异常发生在此代码的末尾。它首先成功打印了所有日志消息,并且我已经验证了Chunk对象没有任何问题:
-(void) testEncodeDecode {
DWChunk *testChunk = [[DWChunk alloc]initWithPosition:CGPointMake(100, 100)];
NSData *testData = [testChunk customEncode];
NSLog(@"datasize= %@", testData);
DWChunk *unencodedChunk = [[DWChunk alloc]initWithData:testData];
NSLog(@"blocks=%@", unencodedChunk.blocks.allValues);
NSLog(@"this message will print");
}
正如我所说,Chunk和Block对象的所有变量都已正确初始化。我怀疑这个问题与不正确的物品释放有关,但我不知道从哪里开始。
编辑:我已启用检查僵尸,现在我收到此错误消息:
2014-10-24 11:38:31.775 DigWorld[10622:60b] *** -[NSConcreteMutableData release]: message sent to deallocated instance 0x81790710
答案 0 :(得分:1)
编辑:
我最初的想法在技术上不正确(读取代码太快......),但实际错误是完全相同的。通过保存blocks
,您只保存指针数组,而不保存实际数据。你可以确定:你在评论中说sizeof(blocks)=3600
和_blocks.allValues.count=900
,所以你只保存900个指针(* 4个字节/指针= 3600个字节)
由[block customEncode]
创建的实际数据随后由ARC处理。
之后读取此数组时,您将获得指向已被标记为已释放的内存块(以前称为NSData
)的指针,从而导致崩溃,并在启用僵尸时解释错误消息。
棘手的部分:由于这是程序的相同实例,并且编码和解码彼此相邻,因此实际内存尚未重新分配/覆盖。因此,您可以获得正确保存对象的印象。但请放心,这种记忆最终会被其他东西覆盖。您可以通过将NSData
保存在磁盘上并在重新运行程序时对其进行解码来确保这一点。
在我看来,你正试图在这里重新发明轮子。
完全为此目的创建了NSCoding
协议:在磁盘上保留对象的图形。 NSKeyedArchiver
类将在经过充分测试和记录的界面中为您提供具有灵活性和平台独立性的磁盘序列化。
你应该利用这种架构。即使您决定NSKeyedArchiver
也创建档案&#34; big&#34;为了您的目的,使用该架构并创建自己的存档。
如果您选择这样做,您可以获得灵感with this open source NSCoder
subclass implementation(免责声明:我写了它)