[英]Objective-C - ARC - NSNumber - Segmentation Fault
我有一個Objective-C程序,我正在使用ARC(自動引用計數),它在第23行引發了一個分段錯誤(參見下面的程序)。
問題 1)為什么會發生分段錯誤?
以下是該計划:
#import<Foundation/Foundation.h>
@interface Car : NSObject
@property (weak) NSNumber* doors;
@end
@implementation Car
@synthesize doors;
@end
int main()
{
system("clear");
@autoreleasepool
{
Car *car1 = [[Car alloc] init];
printf("1\n");
NSNumber *d1 = [[NSNumber alloc] initWithInteger: 4];
printf("2\n");
car1.doors = d1; //Segmentation fault.. why ?
printf("3\n");
}
printf("---- end\n");
return(0);
}
輸出:
1
2
Segmentation fault: 11
恭喜:您在Core Foundation中發現了一個錯誤!
比爾懷疑,這與Lion中的標記指針有關。 當你創建
NSNumber *d1 = [[NSNumber alloc] initWithInteger: 4];
d1
不指向實際的NSNumber
實例。 相反, d1
是包含0x4c3
的標記指針,其中0x4
是標記指針中的有效負載。
當您嘗試使用標記指針作為弱屬性的值時,Objective-C運行時執行的步驟之一是將-allowsWeakReference
發送到實例以驗證它是否可以用作弱引用。 由於NSNumber
不會覆蓋該方法,因此執行NSObject
的默認實現,然后發送_isDeallocating
,后者又調用_CFIsDeallocating()
,如此堆棧跟蹤所示:
#0 0x00007fff8ccdbacd in _CFIsDeallocating ()
#1 0x00007fff8ccd3119 in -[__NSCFNumber _isDeallocating] ()
#2 0x00007fff8be34b15 in -[NSObject(NSObject) allowsWeakReference] ()
#3 0x0000000100000ded in main () at test.m:12
如果您閱讀CFRuntime.c ,您將看到_CFIsDeallocating()
將相應的指針強制轉換為CFRuntimeBase *
以讀取_cfinfo
。 對於普通的Core Foundation對象,這是有效的,因為每個常規Core Foundation引用都指向以isa
指針開頭的實例,后跟_cfinfo
。 但是,標記指針不指向實際(已分配)內存,因此_CFIsDeallocating()
嘗試取消引用無效的指針,從而導致分段錯誤。
您應該向Apple提交錯誤報告 。 同時,使用strong
或unsafe_unretained
財產。
編輯:要獲取回溯,使用-g
構建可執行文件以包含調試信息,例如:
$ clang test.m -g -fobjc-arc -framework Foundation -o test
並使用GDB運行它:
$ gdb test
…
(gdb) run
該程序將崩潰:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000000004cb
0x00007fff8ccdbacd in _CFIsDeallocating ()
使用GDB中的bt
命令獲取回溯:
(gdb) bt
#0 0x00007fff8ccdbacd in _CFIsDeallocating ()
#1 0x00007fff8ccd3119 in -[__NSCFNumber _isDeallocating] ()
#2 0x00007fff8be34b15 in -[NSObject(NSObject) allowsWeakReference] ()
#3 0x00007fff875173a6 in weak_register_no_lock ()
#4 0x00007fff875179f9 in objc_storeWeak ()
#5 0x0000000100000c0e in -[Car setDoors:] (self=0x100113f60, _cmd=0x100000e7a, doors=0x4c3) at test.m:8
#6 0x0000000100000d45 in main () at test.m:23
然后quit
命令退出GDB:
(gdb) quit
在Xcode中,使用Mac OS X>應用程序>命令行工具模板。 運行程序時,Xcode應自動在調試區域顯示GDB提示。 如果調試區域未顯示在標准編輯器中,請選擇“視圖”>“調試區域”>“顯示調試區域”。
編輯:此錯誤已在OS X v10.7.3中修復。
發布回溯。 還 - 什么平台?
它可能是與NSNumber
和標記指針相關的錯誤(如果針對64位OS X)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.