[英]Mac OS X, Objective-C crash with NSMutableArray
環境:Mac OS 10.8.5,XCode 5.1.1
問題:崩潰的obj_msgsend
上addObject
消息到NSMutableArray
免責聲明:我是Objective-C的新手,所以這可能是一個明顯的錯誤。 但這很神秘。
細節:
盡管有問題的確切表現與整個應用程序有所不同,但我已經能夠將問題簡化為一個小的測試用例。
這是@interface:
@interface ObjCQueue : NSObject
+ (void) push: (NSString *)calEvent;
+ (NSString *) pop;
@end
這是Objective-C類的實現。
#import <Foundation/Foundation.h>
#include "ObjcQueue.h"
NSMutableArray *qArray;
@implementation ObjCQueue
{
}
+ (void) init
{
qArray = [[NSMutableArray alloc] init];
// NSLog(@"(init)qArray class is: %@\n", NSStringFromClass([qArray class]));
}
+ (void) push:(NSString *)calEvent
{
[qArray addObject:calEvent];
}
+ (NSString *) pop
{
// This will return nil if there's no first object
NSString *retEvent = [qArray objectAtIndex:0];
// Don't delete the front of the queue if nothing is there
if (retEvent != nil)
[qArray removeObjectAtIndex:0];
return retEvent;
}
@end
而main.m這樣做:
int main(int argc, const char * argv[])
{
@autoreleasepool {
[ObjCQueue init];
[ObjCQueue push:@"Pushed thing"];
NSLog(@"Popped: %@\n", [ObjCQueue pop]);
}
return 0;
}
目前,讓我們忽略我怎么做是完全錯誤的可能性(我們將繼續討論)。
如果我按原樣運行此代碼,那么objc_msgSend
會崩潰,該崩潰由[ObjCQueue push:]
發送的addObject
消息調用
神秘的部分是,如果我取消注釋[ObjCQueue init]
的NSLog
調用,一切都會正常運行。
在較大的應用程序中,我看到了另一個問題。 該失敗也發生在push
方法中,除了運行時錯誤外,我說addObject
是無效的選擇器。 在這種情況下,當我檢查qArray
的類型時,它具有NSDictionary
的類型(這是從內存中qArray
的,並不是完全按照這種方式拼寫的),而不是NSMutableArray
。 另外,在較大的應用程序中,在init
方法中添加NSLog
調用可使所有操作順利進行。
在這個較小的示例中, qArray
的類型始終顯示為NSMutableArray
。
在類似問題的其他答案中,這意味着與qArray
對應的對象將被覆蓋和/或過早釋放。 我看不到這怎么發生,因為它是全局的,並且ObjCQueue僅具有類方法,並且沒有創建它的實例。 [ObjCQueue init]
僅被調用一次。
另一位數據:在這種較小的情況下, qArray
的顯示位置不同(在調試器中)。
在init
中,如果崩潰,則qArray獲得其值后,調試器將立即顯示:
Printing description of qArray:
<__NSArrayM 0x10010a680>(
)
但是在push
,就在調用addObject
方法之前,調試器顯示:
Printing description of qArray:
(NSMutableArray *) qArray = 0x000000010010a680
值是相同的,但是類型有點不同(也許)。 在沒有崩潰的情況下,兩種情況下的顯示都是相同的(它們都與第一個顯示相同)
這可能不是初始化qArray
的最佳方法(或者可能是公然的錯誤方法),我可以接受。 但是, 為什么增加NSLog
調用后行為會發生變化?
任何幫助/見解將不勝感激。
-Eric
PS這是XCode項目: 錯誤測試
問題是因為ARC在調用push
之前釋放了qArray
,所以您正在調用已經釋放的對象。 解決此問題的一個好方法是將您的類更改為實際實例,或者創建一個單例,以便ARC知道保留數組,而不僅僅是在初始化后立即釋放它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.