我正在使用垃圾收集的Mac应用程序。应用程序崩溃了一些用户,崩溃日志表明它与内存损坏或内存丢失有关。
我发布了以下崩溃日志的重要部分。
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Application Specific Information:
objc[81831]: garbage collection is ON
Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 libSystem.B.dylib 0x00007fffffe00847 __memcpy + 167
1 libauto.dylib 0x00007fff82718170 auto_zone_write_barrier_memmove + 96
2 libauto.dylib 0x00007fff8271916e auto_realloc(_malloc_zone_t*, void*, unsigned long) + 878
3 libSystem.B.dylib 0x00007fff8346e0db malloc_zone_realloc + 92
4 com.apple.Foundation 0x00007fff83169836 _NSMutableDataGrowBytes + 652
5 com.apple.Foundation 0x00007fff83169513 -[NSConcreteMutableData appendBytes:length:] + 101
6 MY.Application 0x000000010000b9cd -[Connection stream:handleEvent:] + 376
7 com.apple.CoreFoundation 0x00007fff85742373 _signalEventSync + 115
8 com.apple.CoreFoundation 0x00007fff857422e4 _cfstream_solo_signalEventSync + 116
发生的情况是,我的应用程序从网络接收数据并将该数据写入NSMutableData对象。我和其他一些开发人员讨论了这个问题,我们最好的猜测是内存被破坏,导致崩溃。
问题是如何防止内存垃圾,以及如何在Xcode中调试这样的错误?
为了完整起见,我还发布导致崩溃的方法代码。
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
case NSStreamEventHasSpaceAvailable: {
if (stream == outputStream) {
[self writeBufferToStream];
}
break;
}
case NSStreamEventOpenCompleted:
if (stream == inputStream) {
readReady = YES;
} else {
writeReady = YES;
}
if ([self isReadyForUse] && [delegate respondsToSelector:@selector(connectionReadyForUse:)])
[delegate connectionReadyForUse:self];
break;
case NSStreamEventHasBytesAvailable: {
if (stream == inputStream) {
int bytesRead = 0;
static uint8_t buffer[kBufferSize];
bytesRead = [inputStream read:buffer maxLength:sizeof(buffer)];
[inBuffer appendBytes:buffer length:bytesRead];
//** Process buffer contents **//
BOOL safe = YES;
while (safe) {
if (inSize <= 0) {
if ([inBuffer length] >= sizeof(uint64_t)) {
memcpy(&inSize, [inBuffer bytes], sizeof(uint64_t));
NSRange rangeToDelete = {0, sizeof(uint64_t)};
[inBuffer replaceBytesInRange:rangeToDelete withBytes:NULL length:0];
} else {
break;
}
}
if (inSize > 0) {
if ([inBuffer length] >= inSize) {
NSMutableData *packetData = [NSMutableData dataWithBytes:[inBuffer bytes] length:inSize];
[delegate connection:self receivedData:packetData];
safe = NO;
NSRange rangeToDelete = {0, inSize};
[inBuffer replaceBytesInRange:rangeToDelete withBytes:NULL length:0];
inSize = 0;
} else {
break;
}
} else {
break;
}
}
}
break;
}
case NSStreamEventErrorOccurred: {
NSError *theError = [stream streamError];
if (stream == inputStream)
if (delegate && [delegate respondsToSelector:@selector(connection:encounteredReadError:)])
[delegate connection:self encounteredReadError:theError];
else{
if (delegate && [delegate respondsToSelector:@selector(connection:encounteredWriteError:)])
[delegate connection:self encounteredWriteError:theError];
}
break;
}
case NSStreamEventEndEncountered: {
if (delegate && [delegate respondsToSelector:@selector(connectionDisconnected:)])
[delegate connectionDisconnected:self];
readReady = NO;
writeReady = NO;
break;
}
default:
break;
}
}
答案 0 :(得分:-1)
保持数据在同一线程中读写。如果必须在多线程中执行此操作,则可以选择锁或屏障以确保该线程安全