簡體   English   中英

iOS-刪除NSMutableArray中的對象會引發NSRangeException

[英]iOS - Removing An Object In NSMutableArray Throws NSRangeException

我正在使用TCP短連接將數據發送到主機。 當我想向主機發送數據時,我將實例化一個套接字,將套接字實例存儲到一個數組中,然后在成功寫入數據后再將其刪除。

這是我的方法:

- (void)connectAndSendData:(NSData *)data
{
    GCDAsyncSocket *asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

    [_connectionDataToBeSentMap setObject:data forKey:[NSValue valueWithNonretainedObject:asyncSocket]];

    NSError *error;

    if(![asyncSocket connectToHost:_host onPort:TCP_COMMUNICATION_PORT withTimeout:TCP_CONNECTION_TIMEOUT error:&error])
    {
        NSLog(@"TCPShortConnection - failed when attempting to connect to host with IP %@", _host);
    }

    [_connectionList addObject:asyncSocket];
}

寫入數據后,我將立即斷開套接字。 因此,連接將在以后刪除:

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    [_connectionList removeObject:sock];

    if(err.code == GCDAsyncSocketConnectTimeoutError)
    {
//        NSLog(@"TCPShortConnection - on connection timed out");

        [_delegate onTCPShortConnectionTimedOut];
    }

    else
    {
//        NSLog(@"TCPShortConnection - on disconnection of socket with host %@", _host);
    }
}

這行[_connectionList removeObject:sock]; 引發NSRangeException。 而且我不知道為什么。 因為我通過刪除空數組中不存在的對象進行了測試,所以不會引發此類異常。

這是日志:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(0x258d9b0b 0x25096dff 0x257ea6d3 0x257ff033 0xfae43 0x1ca94d 0x4ccba7 0x4d8eff 0x4d87f1 0x2560ae0d 0x2560a9fc)
libc++abi.dylib: terminating with uncaught exception of type NSException

屏幕截圖:

在此處輸入圖片說明

編輯:

請不要以為這不是100%發生。

猜猜:您正在從不同的線程訪問NSMutableArray

說明:

  1. NSMutableArray不是線程安全的,並發讀寫也不安全-如果從GCD並發隊列訪問該數組,可能會發生這種情況。

  2. GCDAsyncSocket使用GCD。 特別是,委托調用是在用戶設置的GCD隊列上調度的,並且此隊列可以是並發的。

  3. 您正在將全局並發隊列之一設置為委托隊列。

解決方案:您應該首先確定是否應使用數組,但我們無法為您確定。 如果需要數組,則它必須是線程安全的。 一種簡單的方法是:

  1. 創建陣列時,還要為此陣列創建一個順序的 GCD隊列。

  2. 要執行從數組讀取的數組方法,請對數組的順序隊列執行同步調度。 您可以使用__block變量從分派的塊中返回結果。

  3. 要對陣列執行寫操作,請使用異步分派到陣列的隊列。

這個簡單的模型可確保在陣列上不能同時發生兩個操作,並且所有讀取和寫入均以分派的順序進行。

正如我在開始時所說的,我猜測對數組的並發訪問是您的問題,您需要確定自己。 如果是這樣,應該修復它。

高溫超導

這里有兩種情況:

情況1:成功將對象添加到_connectionList數組中時。

   [_connectionList addObject:asyncSocket];

在這種情況下,不會發生此類異常。

[_connectionList removeObject:sock];

從_connectionList數組中成功刪除該對象。

情況2:當對象未成功添加到_connectionList數組中時。

在此引發異常,

[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]

因為該對象未成功添加到_connectionList數組中。

因此,這個問題稱為讀寫器問題

因為NSMutableArray不是線程安全的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM