2014-08-29 49 views
0

我正在使用遊戲中心在兩個玩家之間發送數據。出於某種原因,我不斷收到一個解除分配的實例消息。下面的代碼:發送到釋放Instantce的消息

- (void)sendGameMove:(uint32_t)i andj:(NSString *)j { 

    MessageMove message; 
    message.message.messageType = kMessageTypeMove; 
    message.i = 1; 
    message.j = @"Testing 1 2 3s"; 
    NSData *data = [NSData dataWithBytes:&message length:sizeof(MessageMove)]; 
    MessageMove * messageMove = (MessageMove *) [data bytes]; 
    NSLog(@"Message I: %i", messageMove->i); 
    NSLog(@"Message J: %@", messageMove->j); 
    [self sendData:data]; 

}

(我在i和j參數填充爲我傳遞了什麼)。在這種方法中的NSLog語句都登錄他們應該怎樣創建NSData對象後,但是當我發送的NSData對象的方法[自送出數據:數據]:

- (void)sendData:(NSData *)data { 
    MessageMove * messageMove = (MessageMove *) [data bytes]; 
    NSLog(@"Message I: %i", messageMove->i); 
    NSLog(@"Message J: %@", messageMove->j); 
    NSError *error; 
    BOOL success = [[GCHelper sharedInstance].match sendDataToAllPlayers:data  withDataMode:GKMatchSendDataReliable error:&error]; 
    if (!success) { 
     [self matchEnded]; 
    } 

}

在聲明NSLog的第一個正常工作,所以我得到:

"Message I: 1" 

在控制檯中,但第二日誌語句,我得到:

"*** -[ respondsToSelector:]: message sent to deallocated instance" 

分解數據對象的代碼在第二種方法中與第一種方法完全相同。有任何想法嗎?

回答

1

我猜測MessageMove是一個結構,如:

typedef struct { 
    int i; 
    NSString *j; 
} MessageMove; 

的問題是,你只發送結構本身的內容。在存儲和網絡上,它會是這個樣子:

01000000 07FCA700 
----------------- 
i  j 

當第二設備接收的消息,並試圖讀取j指針,它崩潰,因爲什麼都沒有:該指針是唯一有效的原始設備。該結構甚至不包含字符串的內容。

要解決此問題,您需要實際發送消息中的字符串。柔性陣列成員是直接在結構存儲串的一種方法:

typedef struct { 
    int32_t i; // explicit integer sizes are a good idea for network protocols 
    int32_t j_length; 
    char j[]; // the flexible array member 
} MessageMove; 

發送:

NSString *s = @"Testing 1 2 3s"; 
NSData *d = [s dataUsingEncoding:NSUTF8StringEncoding]; 
size_t messageSize = sizeof(MessageMove) + [d length]; 
MessageMove *mm = calloc(1, messageSize); 
mm->i = 1; 
mm->j_length = [d length]; 
memcpy(mm->j, [d bytes], [d length]); 
[self sendData:[NSData dataWithBytes:mm length:messageSize]]; 

接收:

MessageMove *mm = (MessageMove *)[data bytes]; 
assert(mm->j_length == [data length] - offsetof(MessageMove, j)); 
NSString *j = [[NSString alloc] initWithBytes:mm->j length:mm->j_length encoding:NSUTF8StringEncoding]; 

斷言防止讀取過去的data的端部緩衝。 offsetof是來自<stddef.h>的宏。


對於比這更復雜的任何事情,我建議序列化併發送plist或JSON代替。他們處理所有的字符串複製細節,並讓你發送數組和字典。

+0

完美運作!!!!!非常感謝你,我已經有這個問題好幾個星期了,沒有人提供新的答案!你是一個拯救生命的人!!!!!!!!! – 2014-08-31 20:46:41

+0

很高興幫助!另一個建議:我建議切換你的Objective-C代碼,以便用ARC進行編譯。特別是,ARC會檢測到將消息結構中的'NSString *'指針自動存儲爲可能不安全。 – 2014-08-31 22:00:53

相關問題