Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 返回指向目标C中已释放对象的uuu不安全u未恢复指针会导致崩溃_Objective C_Automatic Ref Counting_Unsafe Unretained - Fatal编程技术网

Objective c 返回指向目标C中已释放对象的uuu不安全u未恢复指针会导致崩溃

Objective c 返回指向目标C中已释放对象的uuu不安全u未恢复指针会导致崩溃,objective-c,automatic-ref-counting,unsafe-unretained,Objective C,Automatic Ref Counting,Unsafe Unretained,问题: // Declare my class with 1 member. @interface MyClass : NSObject { __unsafe_unretained id m_MyMember; } @end // **************************************************************************************************** // // Implement my cla

问题

// Declare my class with 1 member.
@interface MyClass : NSObject
{
    __unsafe_unretained id      m_MyMember;
}
@end

// **************************************************************************************************** //

// Implement my class.
@implementation MyClass

// Setter
-(void)SetMember:(__unsafe_unretained id)member
{
    m_MyMember = member;
}

// Getter: by passing parameter by reference
-(void)GetMember1:(__unsafe_unretained id*)member
{
    *member = m_MyMember;   // No problem.
}

// Getter: by return value
-(__unsafe_unretained id)GetMember2
{
    return m_MyMember;  // Crashed in here!
}

@end

// **************************************************************************************************** //

//! Application entry point.
int main(int argc, char *argv[])
{
    @autoreleasepool
    {       
        {
            // Create an object that dies immediately. deadObj is a dangling pointer.
            __unsafe_unretained id deadObj = [[NSMutableString alloc] initWithFormat:@"%d", 12];

            // Create my object.
            MyClass* myObject = [[MyClass alloc] init];

            // Assign my member.
            [myObject SetMember:deadObj];

            // Get back my member: by passing parameter by reference
            __unsafe_unretained id unsafePointer1;
            [myObject GetMember1:&unsafePointer1];  // No problem.

            // Get back my member: by return value
            __unsafe_unretained id unsafePointer2;
            unsafePointer2 = [myObject GetMember2]; // Crashed in here!

            int BreakpointHere = 0;
        }
    }
}
我有一个
\u不安全\u未保存的id
指针,指向一个已发布的对象。到目前为止还不错,只要我根本不“使用”指针(特别是,我不通过指针调用任何方法)。但是,当我试图从方法返回其值时,它会崩溃,即使我已明确指定返回值的类型为
\uuuuuunsafe\uunrepairedid
。为什么呢?我想如果我使用
\uuuuuunretained
,它根本不会调用
retain
/
release
/
autorelease
这样的方法?我想我可以使用
\uuuuunsafe\uunrepairedid
,就像它是
void*
(意思是它只做简单的本地赋值)

环境

// Declare my class with 1 member.
@interface MyClass : NSObject
{
    __unsafe_unretained id      m_MyMember;
}
@end

// **************************************************************************************************** //

// Implement my class.
@implementation MyClass

// Setter
-(void)SetMember:(__unsafe_unretained id)member
{
    m_MyMember = member;
}

// Getter: by passing parameter by reference
-(void)GetMember1:(__unsafe_unretained id*)member
{
    *member = m_MyMember;   // No problem.
}

// Getter: by return value
-(__unsafe_unretained id)GetMember2
{
    return m_MyMember;  // Crashed in here!
}

@end

// **************************************************************************************************** //

//! Application entry point.
int main(int argc, char *argv[])
{
    @autoreleasepool
    {       
        {
            // Create an object that dies immediately. deadObj is a dangling pointer.
            __unsafe_unretained id deadObj = [[NSMutableString alloc] initWithFormat:@"%d", 12];

            // Create my object.
            MyClass* myObject = [[MyClass alloc] init];

            // Assign my member.
            [myObject SetMember:deadObj];

            // Get back my member: by passing parameter by reference
            __unsafe_unretained id unsafePointer1;
            [myObject GetMember1:&unsafePointer1];  // No problem.

            // Get back my member: by return value
            __unsafe_unretained id unsafePointer2;
            unsafePointer2 = [myObject GetMember2]; // Crashed in here!

            int BreakpointHere = 0;
        }
    }
}
  • 在Xcode 4.4.1上开发
  • 使用iOS SDK 5.1
  • ARC
    已启用
  • iphone4.3/5.0/5.1模拟器上运行
    iphone4.3设备
  • Debug
    Release
    生成时崩溃
源代码

// Declare my class with 1 member.
@interface MyClass : NSObject
{
    __unsafe_unretained id      m_MyMember;
}
@end

// **************************************************************************************************** //

// Implement my class.
@implementation MyClass

// Setter
-(void)SetMember:(__unsafe_unretained id)member
{
    m_MyMember = member;
}

// Getter: by passing parameter by reference
-(void)GetMember1:(__unsafe_unretained id*)member
{
    *member = m_MyMember;   // No problem.
}

// Getter: by return value
-(__unsafe_unretained id)GetMember2
{
    return m_MyMember;  // Crashed in here!
}

@end

// **************************************************************************************************** //

//! Application entry point.
int main(int argc, char *argv[])
{
    @autoreleasepool
    {       
        {
            // Create an object that dies immediately. deadObj is a dangling pointer.
            __unsafe_unretained id deadObj = [[NSMutableString alloc] initWithFormat:@"%d", 12];

            // Create my object.
            MyClass* myObject = [[MyClass alloc] init];

            // Assign my member.
            [myObject SetMember:deadObj];

            // Get back my member: by passing parameter by reference
            __unsafe_unretained id unsafePointer1;
            [myObject GetMember1:&unsafePointer1];  // No problem.

            // Get back my member: by return value
            __unsafe_unretained id unsafePointer2;
            unsafePointer2 = [myObject GetMember2]; // Crashed in here!

            int BreakpointHere = 0;
        }
    }
}
调用堆栈(iPhone 4.3模拟器/iOS 4.3设备):

调用堆栈(iPhone 5.0/5.1模拟器):


我认为这种行为可以用自动参考计数文档中的以下信息来解释:

一种方法或函数,它返回一个可保留的对象类型,但不返回 不返回保留值必须确保对象仍然有效 越过返回边界

从此类函数或方法返回时,ARC保留该值 在对return语句求值时,将所有 然后平衡保留,同时确保 价值跨越调用边界存在。在最坏的情况下,这可能 涉及自动释放,但调用方不得假定该值为 实际上在自动释放池中

函数
GetMember2
返回一个
id
,它是一个可保留的对象类型。因此,ARC编译器添加
retain
/
autorelease
调用,以确保返回的对象在函数返回时仍然有效。这会崩溃,因为
m_MyMember
未指向有效对象


将返回类型声明为
(\uuuu unsafe\u unrepaired id)
不会改变此行为,事实上,我假设此处忽略了
\uuuu unsafe\u unrepaired

我认为可以使用自动引用计数文档中的以下信息来解释此行为:

一种方法或函数,它返回一个可保留的对象类型,但不返回 不返回保留值必须确保对象仍然有效 越过返回边界

从此类函数或方法返回时,ARC保留该值 在对return语句求值时,将所有 然后平衡保留,同时确保 价值跨越调用边界存在。在最坏的情况下,这可能 涉及自动释放,但调用方不得假定该值为 实际上在自动释放池中

函数
GetMember2
返回一个
id
,它是一个可保留的对象类型。因此,ARC编译器添加
retain
/
autorelease
调用,以确保返回的对象在函数返回时仍然有效。这会崩溃,因为
m_MyMember
未指向有效对象

将返回类型声明为
(\uuu unsafe\u unrepaired id)
不会改变此行为,事实上,我假设这里忽略了
\uuuunsafe\u unrepaired

经验教训:1。始终在
\uuuu不安全\u未恢复的
指针的指针对象死亡之前将其置零。2.改用
\uu-weak
(需要iOS 5运行时)。经验教训:1。始终在
\uuuu不安全\u未恢复的
指针的指针对象死亡之前将其置零。2.改用
\uu弱
(需要iOS 5运行时)。