簡體   English   中英

Objective-C - ARC - NSNumber - 分段故障

[英]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提交錯誤報告 同時,使用strongunsafe_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.

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