2015-07-20 33 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}; 
相關問題