2014-08-29 26 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

相关问题