是否故意错误编码的惰性初始化:
-(X*) prop {
if (!prop) {
prop = [[Prop alloc] init];
return prop;
}
// RETURN SHOULD BE HERE
}
然而,由于下面生成的代码序列,“正确的事情”吗?
- 将 prop 加载到 rax 中进行测试
- 在任何情况下都返回 rax
是否故意错误编码的惰性初始化:
-(X*) prop {
if (!prop) {
prop = [[Prop alloc] init];
return prop;
}
// RETURN SHOULD BE HERE
}
然而,由于下面生成的代码序列,“正确的事情”吗?
这不是故意的,即使它有效,你也不应该依赖它。例如,考虑以下情况:
- (NSString *)someString {
if (! someString) {
someString = [[NSString alloc] initWithFormat:@"%d", 5];
return someString;
}
}
编译时gcc -O0
:
movq -24(%rbp), %rdx
movq _OBJC_IVAR_$_SomeClass.someString@GOTPCREL(%rip), %rax
movq (%rax), %rax
leaq (%rdx,%rax), %rax
movq (%rax), %rax
testq %rax, %rax
并且代码确实有效,因为正如您所注意到的,ivar 被加载到RAX
.
但是,当编译时gcc -O3
:
movq %rdi, %rbx
addq _OBJC_IVAR_$_SomeClass.someString(%rip), %rbx
cmpq $0, (%rbx)
je L5
L4:
movq (%rsp), %rbx
movq 8(%rsp), %r12
糟糕,没有返回值RAX
- ivar 已加载到RBX
. 此代码在第一次调用(延迟初始化 ivar)中有效,但在第二次调用中崩溃。
是不是故意的,一个错误编码的惰性初始化:
不。
您很幸运使用了标准返回寄存器。永远不要依赖它。事实上,它应该给你一个编译器警告。