5

を使用しNSInputStreamてファイルからデータを読み取ります。maxLength49152 より大きいとクラッシュします。

クラッシュすると、毎回ではありませんが、時々、次のメッセージが表示されます。

*** キャッチされていない例外 'NSInvalidArgumentException' が原因でアプリを終了しています。

私の計算では、524288 はまだその最大値よりも小さく、戻り値に収まる可能性があります。私は何を取りこぼしたか?

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
    switch (eventCode)
    {
        case NSStreamEventHasBytesAvailable:
        {
            NSInteger bufferSizeNumber = 524288;   //this one will crash.
//            NSInteger bufferSizeNumber = 491520;  // this one will work.

            uint8_t buf[bufferSizeNumber];
            unsigned int len = 0;

            len = [_stream read:buf maxLength:bufferSizeNumber];   //crashing at this line

            // more code ...

        }
        // more  code...
    }
}

編集:(これはその動作の重要な部分だと思います)

バックグラウンド スレッドで「開始」すると、bufferSizeNumber は上記のように動作します。しかし、メインスレッドで「開始」すると、クラッシュする前に bufferSizeNumber が最大 943713 になる可能性があります。

- (void)start
{
    _stream.delegate = self;
    [_stream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                       forMode:NSDefaultRunLoopMode];
    [_stream open];
    [[NSRunLoop currentRunLoop] run];
}
4

1 に答える 1

11

あなたの問題は、いわゆる「スタック オーバーフロー」です (以前に聞いたことがあるかもしれません)。

メソッドは、可変長配列を使用してスタックにバッファを割り当てます。

uint8_t buf[bufferSizeNumber];

バッファのサイズが大きすぎて現在のスタックのサイズをオーバーフローする場合、動作は未定義です。未定義の動作により、クラッシュが発生するか、期待どおりに動作する可能性があります。観察しているだけです。

512kB は巨大なバッファです。特に、バックグラウンド スレッドがまさにこのサイズのスタックを取得する iOS ではそうです。

ヒープに割り当てる必要があります。

NSInteger bufferSizeNumber = 524288;
NSMutableData *myBuffer = [NSMutableData dataWithLength:bufferSizeNumber];

uint8_t *buf = [myBuffer mutableBytes];
unsigned int len = 0;

len = [_stream read:buf maxLength:bufferSizeNumber];
// more code ...
于 2014-02-24T15:34:57.410 に答える