2

我最近开始使用发布版本(管理方案并设置从调试到发布的运行)来测试我的应用程序。我注意到的是,有时我会在流方法中弹出以下错误,我似乎无法找到找到错误的方法。这在调试模式下完美运行,但在发布版本中,除了 SIGABRT 消息之外,我没有收到任何通知。我也不知道如何检查模拟器上的崩溃日志以查看问题所在。下面我附上了崩溃的堆栈跟踪:

#0  0x918749c6 in __pthread_kill ()
#1  0x916c0f78 in pthread_kill ()
#2  0x916b1ce3 in __abort ()
#3  0x916ae64a in __stack_chk_fail ()
#4  0x00006d0d in -[MainViewController processMessage:len:] (_cmd=0x9ceb9, msg=0xdfd7004 "Login="User" Pass="Pass" Id="1234" PlayerId="345" Location="12,35" Color="Red" PlayerId="65" Location="180,0" Color="Blue" PlayerId="29" Location="0,200" Color="..., len=333295) at /Users/seb/Desktop/Tutorials/Networking/MainViewController.m:850
#5  0x000044b3 in -[MainViewController stream:handleEvent:] (_cmd=0x17a0410, stream=<value temporarily unavailable, due to optimizations>, eventCode=<value temporarily unavailable, due to optimizations>) at /Users/seb/Desktop/Tutorials/Networking/MainViewController.m:260
#6  0x01716501 in _inputStreamCallbackFunc ()
#7  0x016e606d in _signalEventSync ()
#8  0x016e67ca in _cfstream_solo_signalEventSync ()
#9  0x016e5e71 in _CFStreamSignalEvent ()
#10 0x016e6727 in CFReadStreamSignalEvent ()
#11 0x020083ad in SocketStream::dispatchSignalFromSocketCallbackUnlocked ()
#12 0x01f64191 in SocketStream::socketCallback ()
#13 0x01f640a1 in SocketStream::_SocketCallBack_stream ()
#14 0x016b3e44 in __CFSocketPerformV0 ()
#15 0x0171997f in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#16 0x0167cb73 in __CFRunLoopDoSources0 ()
#17 0x0167c454 in __CFRunLoopRun ()
#18 0x0167bdb4 in CFRunLoopRunSpecific ()
#19 0x0167bccb in CFRunLoopRunInMode ()
#20 0x0226f879 in GSEventRunModal ()
#21 0x0226f93e in GSEventRun ()
#22 0x0066aa9b in UIApplicationMain ()
#23 0x0000201b in main (argc=1, argv=0xbffff5e0) at /Users/seb/Desktop/Tutorials/Networking/main.m:14

来自流的案例声明:handleevent 发生崩溃的地方:

case NSStreamEventHasBytesAvailable:
        {
            if (stream == inputStream)
            {
                NSLog(@"NSStreamEventHasBytesAvailable");

                uint8_t buffer[4096];
                unsigned int len = 0;
                NSInputStream* inputstream = (NSInputStream*)stream;
                len = [inputstream read:buffer maxLength:sizeof(buffer)];

                // Check if our stream is still valid
                if([inputstream streamError] != nil)
                {
                    //We lost our connection to the host
                    NSError *theError = [stream streamError];
                    [self setConnectError:[NSString stringWithFormat:@"Error %i: %@",
                                                            [theError code], [theError localizedDescription]]];

                    break;
                }

                [streamIncomingData appendBytes:buffer length:len];

                int processedBytes = 0;
                while (true)
                {
                    if ([streamIncomingData length] >= processedBytes + sizeof(uint32_t))
                    {
                        const char* bufferstart = ((const char*)[streamIncomingData mutableBytes]) + processedBytes;
                        uint32_t sz_n;
                        memcpy(&sz_n, bufferstart, sizeof(sz_n));
                        uint32_t sz_h = htonl(sz_n);

                        if ([streamIncomingData length] >= processedBytes + sz_h + sizeof(uint32_t))
                        {
                            [self processMessage:bufstart + sizeof(uint32_t) len:sz_h];
                            processedBytes += sz_h + sizeof(uint32_t);
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                if (processedBytes)
                {
                    if (processedBytes < [streamIncomingData length])
                    {
                        NSMutableData *newdata = [NSMutableData dataWithBytes:[streamIncomingData bytes] + processedBytes length:[streamIncomingData length] - processedBytes];
                        [streamIncomingData setData:newdata];
                    }
                    else
                    {
                        [streamIncomingData setLength:0];
                    }
                }
            }

            break;
        }

进程消息方法:

- (void)processMessage:(const char*)msg len:(int)len
{
    NSLog(@"processMessage start (%d)", len);
    {
        char buffer[len + 1];
        memcpy(buffer, msg, len);
        buffer[len + 1] = '\0';
        NSLog(@"%s", buffer);
    }

    NSLog(@"processMessage end");
}

任何意见是极大的赞赏。

4

1 回答 1

3

buffer您通过尝试在 bounds 之外分配空终止符来破坏堆栈len + 1。正确的代码是:

    char buffer[len + 1];
    memcpy(buffer, msg, len);
    buffer[len] = '\0';
    NSLog(@"%s", buffer);

您所做的是未定义的行为,并且将未定义的行为与为发布模式完成的优化相结合很可能是您仅在发布模式下看到此问题的原因。

于 2012-04-11T16:25:46.120 回答