Objective c 关于GCC优化级别,影响块中弱变量的规则是什么?
在下面的代码中,当我在GCC_OPTIMIZATION_LEVEL设置为None的情况下运行它时,执行工作与我预期的一样,并将以下内容打印到控制台:Objective c 关于GCC优化级别,影响块中弱变量的规则是什么?,objective-c,automatic-ref-counting,block,Objective C,Automatic Ref Counting,Block,在下面的代码中,当我在GCC_OPTIMIZATION_LEVEL设置为None的情况下运行它时,执行工作与我预期的一样,并将以下内容打印到控制台: My Obj - SomeObj My obj - (null) 但是,当我将GCC_优化_级别设置为Xcode目标配置中最快、最小的级别时(正如发布版本通常所做的那样),我会在控制台上打印以下内容: My Obj - SomeObj My obj - (null) 当我将对象存储到[Foo doSomething]中的uu弱id myOb
My Obj - SomeObj
My obj - (null)
但是,当我将GCC_优化_级别设置为Xcode目标配置中最快、最小的级别时(正如发布版本通常所做的那样),我会在控制台上打印以下内容:
My Obj - SomeObj
My obj - (null)
当我将对象存储到[Foo doSomething]中的uu弱id myObj变量中时,该对象似乎被释放。如果我从myObj变量中删除uu弱标志,那么当GCC_优化_级别设置为最快、最小时,代码将按预期运行
我基于另一个项目中的类似模式构建了这个示例,并添加了_弱标志,因为我遇到了一个保留周期。retain cycle警告消失了,但当我为发布构建时,我发现myObj在到达我在本例中记录它的位置时将为零
我设置弱标志违反了什么规则
#import "FFAppDelegate.h"
///////////////////////////////////////////////////////
@interface SomeObject : NSObject
@end
@implementation SomeObject
- (NSString *)description; {
return @"SomeObject";
}
@end
///////////////////////////////////////////////////////
@interface Factory : NSObject
@end
@implementation Factory
- (id)generateObj {
id myObj = nil;
if (!myObj) {
SomeObject *anObj = [[SomeObject alloc] init];
myObj = anObj;
}
return myObj;
}
@end
///////////////////////////////////////////////////////
@interface Bar : NSObject
- (id)barObj;
@end
@implementation Bar
{
Factory *factory;
}
- (id)init {
self = [super init];
if (self) {
factory = [[Factory alloc] init];
}
return self;
}
- (id)barObj {
id anObj = [factory generateObj];
return anObj;
}
@end
///////////////////////////////////////////////////////
@interface Foo : NSObject
@property (strong) Bar *aBar;
- (void)doSomething;
@end
@implementation Foo
- (id)init {
self = [super init];
if (self) {
_aBar = [[Bar alloc] init];
}
return self;
}
- (void)doSomething {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
__weak id myObj = [self.aBar barObj];
NSLog(@"My Obj - %@", myObj);
});
}
@end
///////////////////////////////////////////////////////
@implementation FFAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Foo *f = [[Foo alloc] init];
[f doSomething];
}
@end
我设置弱标志违反了什么规则
#import "FFAppDelegate.h"
///////////////////////////////////////////////////////
@interface SomeObject : NSObject
@end
@implementation SomeObject
- (NSString *)description; {
return @"SomeObject";
}
@end
///////////////////////////////////////////////////////
@interface Factory : NSObject
@end
@implementation Factory
- (id)generateObj {
id myObj = nil;
if (!myObj) {
SomeObject *anObj = [[SomeObject alloc] init];
myObj = anObj;
}
return myObj;
}
@end
///////////////////////////////////////////////////////
@interface Bar : NSObject
- (id)barObj;
@end
@implementation Bar
{
Factory *factory;
}
- (id)init {
self = [super init];
if (self) {
factory = [[Factory alloc] init];
}
return self;
}
- (id)barObj {
id anObj = [factory generateObj];
return anObj;
}
@end
///////////////////////////////////////////////////////
@interface Foo : NSObject
@property (strong) Bar *aBar;
- (void)doSomething;
@end
@implementation Foo
- (id)init {
self = [super init];
if (self) {
_aBar = [[Bar alloc] init];
}
return self;
}
- (void)doSomething {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
__weak id myObj = [self.aBar barObj];
NSLog(@"My Obj - %@", myObj);
});
}
@end
///////////////////////////////////////////////////////
@implementation FFAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Foo *f = [[Foo alloc] init];
[f doSomething];
}
@end
在您的示例中,没有对从[self.aBar barObj]
返回的实例的强引用。因此,您不能假设在读取myObj
变量时实例将处于活动状态
在未优化的构建中,返回的实例已添加到自动释放池中,因此在打印myObj
时仍处于活动状态。您可以通过在-[SomeObject dealloc]
中设置断点来验证这一点
在优化的构建中,ARC避免了自动释放池,因此返回的实例将立即释放
有关更多信息,请参阅。具体而言:
当从这样的函数或方法返回时,ARC会在return语句的求值点保留该值,然后离开所有局部作用域,然后平衡retain,同时确保该值跨越调用边界。在最坏的情况下,这可能涉及自动释放,但调用者不得假设该值实际上在自动释放池中
当使用
\uu-weak
来避免保留循环时,您必须确保在其他地方有一个强引用来保持对象的活动状态。也许您应该使用Apple的默认编译器LLVM,而不是GCC
编辑:而且你的“工厂”方法看起来是错误的。例如,在该if中,对象始终为零。浏览一下:为了防止保留循环,您需要在块外创建一个弱引用。这正是我为解决此问题所做的。谢谢。我正在使用LLVM。LLVM使用GCC_优化_级别标志。