Избегайте повреждения памяти - PullRequest
0 голосов
/ 17 февраля 2011

Я работаю над приложением 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...