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运行时)。