【问题标题】:Message Sent To Deallocated Instantce消息发送到解除分配的实例
【发布时间】:2014-08-29 22:53:48
【问题描述】:

我正在使用游戏中心在两个玩家之间发送数据。出于某种原因,我不断收到解除分配的实例消息。代码如下:

- (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 对象发送到方法 [self sendData:data] 时:

- (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"

第二种方法中分解数据对象的代码与第一种方法中的完全相同。有什么想法吗?

【问题讨论】:

    标签: ios objective-c ipad methods game-center


    【解决方案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。他们为你处理所有的字符串复制细节,让你也可以发送数组和字典。

    【讨论】:

    • 完美运行!!!!!!!非常感谢,我已经有这个问题好几个星期了,没有人新的答案!你是救生员!!!!!!!!!
    • 很高兴为您提供帮助!另一个建议:我建议将您的 Objective-C 代码切换为使用 ARC 编译。特别是,ARC 会自动检测到将 NSString * 指针存储在消息结构中可能不安全。
    猜你喜欢
    • 2014-05-11
    • 2013-06-04
    • 2012-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多