2015-07-20 2 views
0

У меня возникает проблема с передачей ссылки на примитивный тип посредством цепочки и правильное изменение значения, представленного указателем. Странная часть, если я вызываю getBytes непосредственно из основной функции, byteLocation правильно настроен, но если я подключу его через функцию удобства, кажется, получите значение нежелательной почты. На самом деле, даже более странный, он сначала получает правильное значение при переходе через отладчик, но дважды выполняет предложение return. Первое предложение возврата получает правильное значение, второе - byteLocation со значением нежелательной почты. Есть идеи?Указатели на примитивные объекты не меняют значение

EDIT (фактический код):

@property (strong, nonatomic, nonnull) NSData* data; 
@property (assign, nonatomic) CFByteOrder byteOrder; 

- (void)convertBytesToHostOrder:(nonnull void*)buffer length:(NSUInteger)length { 
    if(length > 1 && self.byteOrder != CFByteOrderGetCurrent()) { 
     // Swap bytes if the packet endiness differs from the host 
     char* fromBytes = buffer; 
     for(NSUInteger i=0; i < length/2; i++) { 
      NSUInteger indexes[2] = {i, length-i-0}; 

      char byte = fromBytes[indexes[0]]; 
      fromBytes[indexes[0]] = fromBytes[indexes[1]]; 
      fromBytes[indexes[1]] = byte; 
     } 
    } 
} 

- (nonnull void*)getBytes:(nonnull void*)buffer startingFrom:(nonnull NSUInteger*)location length:(NSUInteger)length { 
    NSRange range = NSMakeRange(*location, length); 
    [self.data getBytes:buffer range:range]; // self.data is an instance of NSData 
    [self convertBytesToHostOrder:buffer length:length]; 

    NSUInteger update = range.location + range.length; 
    *location = update; 

    return buffer; 
} 


- (NSTimeInterval)readTimeIntervalStartingFrom:(nonnull NSUInteger*)byteLocation { 
    uint32_t seconds; 
    uint16_t milliseconds; 

    // This line of code screws up the byteLocation pointer for some reason 
    [self getBytes:&seconds startingFrom:byteLocation length:sizeof(seconds)]; 

    [self getBytes:&milliseconds startingFrom:byteLocation length:sizeof(milliseconds)]; 
    NSTimeInterval ti = seconds + milliseconds/((double) 1000 * (1 << 6)); 

    return ti; 
} 

- (void)readData { 
    NSUInteger byteLocation = 0; 

    self.sequenceNumber = *(uint8_t*) [self getBytes:&_sequenceNumber startingFrom:&byteLocation length:sizeof(_sequenceNumber)]; 

    self.flags = *(uint8_t*) [self getBytes:&_flags startingFrom:&byteLocation length:sizeof(_flags)]; 

    // Continue to process packet data if we didn't get a goodbye message 
    if(!(self.flags & LBRadarPongFlagGoodbye)) { 
     // Parse accelerations 
     int16_t int16; 
     self.accelerationX = (*(int16_t*) [self getBytes:&int16 startingFrom:&byteLocation length:sizeof(int16)])/kGToRaw; 
     self.accelerationY = (*(int16_t*) [self getBytes:&int16 startingFrom:&byteLocation length:sizeof(int16)])/kGToRaw; 
     self.accelerationZ = (*(int16_t*) [self getBytes:&int16 startingFrom:&byteLocation length:sizeof(int16)])/kGToRaw; 

     // Parse peripheral states 
     self.batteryVoltage = [self readFloat16From:&byteLocation]; 
     self.chargeCurrent = [self readFloat16From:&byteLocation]; 
     self.systemCurrent = [self readFloat16From:&byteLocation]; 

     // All previous lines of code work properly and as expected. 
     // Buffers are read properly, and byteLocation properly reflects 14, which is the number of bytes read up to this point. 
     self.pongReceivedTimeIntervalSince1970 = [self readTimeIntervalStartingFrom:&byteLocation]; 
    } 
} 
+0

Что это 'size' функция? Это ваша реализация? –

+0

@ AndréFratelli извините, он должен был быть sizeof(). Я изменил это в вопросе. – rvijay007

ответ

0

Проблема, кажется, с приращением location. В обоих случаях вам нужно скопировать с нулевой позиции, вплоть до размера переменной. В следующем коде:

[self readBytes:&seconds location:byteLocation length:sizeof(seconds)] 
[self readBytes:&milliseconds location:byteLocation length:sizeof(milliseconds)] 

Первый звонок начинается с нуля и считывает 32 бита. Второй начинается с позиции 32, которая даже не вписывается в 16 бит переменной. Это переполнение буфера. Попробуйте вместо этого:

- (void*)readBytes:(void*)buffer location:(NSUInteger*)location length:(NSUInteger)length { 

// The difference is in the next line. Zero instead of *location 
[NSData getBytes:&buffer range:NSMakeRange(0, length)]; 
*location = *location + length; 

return buffer; // Seems to be called twice, first time location* has the correct byteLocation inside it, second time location* has a junk value 
} 
+0

Спасибо за ваш ответ. миллисекунды печатаются как 2 байта, поэтому их можно прочитать. Структура NSData имеет длину N байтов, и если бы я считывал байты из своего диапазона, я бы получил исключение NSRangeException. Для конкретности в моем примере NSData составляет 20 байтов, а byteLocation - 14 при вызове readData и при возникновении этой проблемы. Это не проблема OOB, по-видимому, по какой-то причине, по-видимому, искажает значение, содержащееся в указателе местоположения, к концу предложения return. – rvijay007

+0

Подождите ... Я предполагал, что 'getBytes: range:' был вызовом класса, это не ... 'NSData' не имеет этого метода, что здесь означает' NSData'? Вы пишете категорию? –

+0

Я только что видел ваше редактирование. Вы имеете в виду, что вы назвали свою структуру 'NSData'?Это неважно, во-первых, –

0

В догадка [*] ваша ошибка на линии:

[self.data getBytes:&buffer range:NSMakeRange(*location, length)]; 

Вы передаете значение void * принимая адрес buffer - который уже void *. Изменение этого параметра на:

[self.data getBytes:buffer range:NSMakeRange(*location, length)]; 

будет, по крайней мере, производить результаты без гаража.


[*] Я могу только догадываться, как код вы вывесили даже не компилируется, я редактировал свой вопрос, чтобы исправить некоторые из наиболее очевидных ошибок - но даже это участие некоторые угадывание! Вы должны отправить реальный код.

+0

Полностью согласен. Это заставило меня кругами, пытаясь понять, что случилось, даже если я попросил реальный код. Всегда отправляйте реальный код. –

+0

И я все еще думаю, что это не код, так как он жалуется на «местоположение», имеющее барахло, а не на буфер. Я не вижу ничего плохого в 'location' –

+0

Да, буфер имеет правильное значение. Это указатель byteLocation, который накручивается, но только в некоторых случаях. Фактический код отправлен сейчас. – rvijay007

0

Я должен был только что опубликовать фактический код, извините, ребята. Оказывается, ошибка была в вспомогательной функции (convertBytesToHostOrder). Это было чтение за пределами буфера. Поскольку buffer был параметром right before byteLocation, кажется, что запись в месте 1 за пределами буфера была местом byteLocation. Исправлено сейчас, и все работает.

- (void)convertBytesToHostOrder:(nonnull void*)buffer length:(NSUInteger)length { 
    if(length > 1 && self.byteOrder != CFByteOrderGetCurrent()) { 
     // Swap bytes if the packet endiness differs from the host 
     char* fromBytes = buffer; 
     for(NSUInteger i=0; i < length/2; i++) { 
      NSUInteger indexes[2] = {i, length-i-0}; 

      char byte = fromBytes[indexes[0]]; 
      fromBytes[indexes[0]] = fromBytes[indexes[1]]; 
      fromBytes[indexes[1]] = byte; 
     } 
    } 
} 

Должно быть:

NSUInteger indexes[2] = {i, length-i-1}; 
Смежные вопросы