Note that there are some explanatory texts on larger screens.

plurals
  1. POAvoid memory trashing
    primarykey
    data
    text
    <p>I'm working on a Mac application that uses garbage collection. The application crashes for a few users and the crash logs indicate that it has something to do with memory corruption or memory trashing.</p> <p>I post the important bit of the crash log below.</p> <pre><code>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 </code></pre> <p>What happens is, my application receives data from the network and writes that data to an NSMutableData object. I have talked about this with some other developers and our best guess is that memory is being trashed, which causes the crash.</p> <p>The question is how do you prevent memory trashing and how do you debug bugs like this in Xcode?</p> <p>For completeness, I also post the code of the method that leads up to the crash.</p> <pre><code>- (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] &amp;&amp; [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 &lt;= 0) { if ([inBuffer length] &gt;= sizeof(uint64_t)) { memcpy(&amp;inSize, [inBuffer bytes], sizeof(uint64_t)); NSRange rangeToDelete = {0, sizeof(uint64_t)}; [inBuffer replaceBytesInRange:rangeToDelete withBytes:NULL length:0]; } else { break; } } if (inSize &gt; 0) { if ([inBuffer length] &gt;= 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 &amp;&amp; [delegate respondsToSelector:@selector(connection:encounteredReadError:)]) [delegate connection:self encounteredReadError:theError]; else{ if (delegate &amp;&amp; [delegate respondsToSelector:@selector(connection:encounteredWriteError:)]) [delegate connection:self encounteredWriteError:theError]; } break; } case NSStreamEventEndEncountered: { if (delegate &amp;&amp; [delegate respondsToSelector:@selector(connectionDisconnected:)]) [delegate connectionDisconnected:self]; readReady = NO; writeReady = NO; break; } default: break; } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload