Objective-C-ARC-NSNumber-分段错误 [英] Objective-C - ARC - NSNumber - Segmentation Fault

查看:116
本文介绍了Objective-C-ARC-NSNumber-分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Objective-C程序,我正在使用ARC(自动引用计数),它在第23行中引发了分段错误(请参见下面的程序).

I have an objective-C program and I am using ARC (Automatic Reference Counting), it throws a segmentation fault in line 23 (see program below).

问题 1)为什么会出现分割错误?

Question 1) Why does the segmentation fault occur ?

以下是程序:

#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中发现了一个错误!

Congratulations: you’ve found a bug in Core Foundation!

比尔怀疑,这与狮子.创建时

As Bill suspected, this is related to tagged pointers in Lion. When you create

NSNumber *d1 = [[NSNumber alloc] initWithInteger: 4];

d1并不指向实际的NSNumber实例.相反,d1是包含0x4c3的带标记的指针,其中0x4是带标记的指针中的有效载荷.

d1 doesn’t point to an actual NSNumber instance. Instead, d1 is a tagged pointer containing 0x4c3, where 0x4 is the payload in the tagged pointer.

当您尝试使用标记的指针作为弱属性的值时,Objective-C运行时执行的步骤之一是将-allowsWeakReference发送到实例以验证其是否可以用作弱引用. .由于NSNumber不会覆盖该方法,因此将执行NSObject中的默认实现,依次发送_isDeallocating,该调用又调用_CFIsDeallocating(),如以下堆栈跟踪所示:

When you try to use a tagged pointer as the value of a weak property, one of the steps executed by the Objective-C runtime is to send -allowsWeakReference to the instance to verify whether it can be used as a weak reference. Since NSNumber doesn’t override that method, the default implementation in NSObject is executed, which in turn sends _isDeallocating, which in turn calls _CFIsDeallocating() as shown in this stack trace:

#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()试图取消引用无效的指针,从而导致分段错误.

If you read CFRuntime.c, you’ll see that _CFIsDeallocating() casts the corresponding pointer to CFRuntimeBase * in order to read _cfinfo. For normal Core Foundation objects, this works because every regular Core Foundation reference points to an instance that starts with the isa pointer, followed by _cfinfo. However, tagged pointers do not point to actual (allocated) memory, so _CFIsDeallocating() tries to dereference a pointer that is not valid, hence the segmentation fault.

您应该向Apple提交错误报告.同时,使用strongunsafe_unretained属性.

You should file a bug report with Apple. In the meanwhile, use a strong or unsafe_unretained property.

以获取回溯信息,并使用-g构建可执行文件以包含调试信息,例如:

to get the backtrace, build your executable with -g to include debug information, e.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命令获取回溯:

Use the bt command in GDB to get the backtrace:

(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提示.如果标准编辑器"中未显示调试区域,请选择视图">调试区域">显示调试区域".

In Xcode, use the Mac OS X > Application > Command Line Tool template. When you run your program, Xcode should automatically show the GDB prompt in the debug area. If the debug area doesn’t show up in the Standard Editor, select View > Debug Area > Show Debug Area.

编辑:此错误已在OS X v10.7.3中修复.

this bug was fixed in OS X v10.7.3.

这篇关于Objective-C-ARC-NSNumber-分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆