2015-07-20 52 views
0

我有一个问题,通过链接传递一个基元类型的引用,并使指针表示的值正确更改。奇怪的部分是,如果我直接从主函数调用getBytesbyteLocation会得到适当的调整,但是如果我通过便利函数将其链接起来,它似乎会获得垃圾值。实际上,即使是怪异的,它在逐步调试时也会得到正确的值,但执行两次return子句。第一个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。在这两种情况下,您都应该从位置0复制到变量的大小。在以下代码中:

[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个字节,当readData被调用时,以及发生此问题时,byteLocation是14。这不是一个OOB问题,因为某种原因,似乎只是在return子句的末尾丢弃了位置指针中的值。 – rvijay007

+0

等待...我假设'getBytes:range:'是一个类调用,它不是......'NSData'没有这个方法,这里的NSData究竟是什么?你写了一个类别吗? –

+0

我刚看到你的编辑。你的意思是你叫你的结构'NSData'?首先,这不是一个好主意 –

0

在猜测[*]你的错误就行了:

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

你是通过采取buffer地址传递一个void *值 - 这已经是一个void *。将其更改为:

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

至少会产生非garabge结果。


[*]为您发布甚至不编译代码,我编辑你的问题纠正一些比较明显的错误,我只能猜测 - 但即使这涉及一些猜测!你应该发布真实的代码。

+0

完全同意。尽管我询问了真正的代码,但它让我圈起来试图弄清楚什么是错误的。始终发布真实的代码。 –

+0

我仍然认为这不是代码,因为他抱怨“位置”有垃圾,而不是缓冲区。我发现没有错'位置' –

+0

是的,缓冲区有正确的值。这是字节位置指针,被搞砸了,但只在某些情况下。现在发布的实际代码。 – rvijay007

0

我应该刚刚发布实际的代码,对不起家伙。原来这个错误发生在一个辅助函数(convertBytesToHostOrder)中。这是读出缓冲区的界限。由于buffer是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}; 
相关问题