这具有编译器中轻微错误功能(也称为错误)的所有特征,即当使用框架头文件中定义为弱链接的符号时,它无法正确评估-weak_framework,因此认为代码无操作。
这意味着优化器很高兴能够从代码中删除 if 检查 - 当我使用一个简单的测试代码时它确实做到了。
#import <Accounts/ACAccountType.h>
#import <stdio.h>
int
main(int argc, char **argv)
{
if (&ACAccountTypeIdentifierFacebook != NULL)
NSLog(@"Hello\n");
return (0);
}
此代码编译为:
$ clang -weak_framework Accounts -framework Foundation weak.m
weak.m:8:10: warning: comparison of address of 'ACAccountTypeIdentifierFacebook' not equal to a null pointer is always true [-Wtautological-pointer-compare]
if (&ACAccountTypeIdentifierFacebook != NULL)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~
1 warning generated.
检查时,表明代码中甚至没有引用ACAccountTypeIdentifierFacebook 符号:
$ nm -m a.out
(undefined) external _NSLog (from Foundation)
(undefined) external ___CFConstantStringClassReference (from CoreFoundation)
0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header
0000000100000f40 (__TEXT,__text) external _main
(undefined) external dyld_stub_binder (from libSystem)
即优化器将其完全删除。您可以使用otool -tv a.out 检查生成的代码,您会发现 if 测试完全被跳过了。
希望它会在编译器的未来版本中得到修复,但是您可以暂时解决这个问题。
为了让编译器认为符号是弱的,它需要显式标记为weak import,这意味着它需要看起来像:
extern NSString * const ACAccountTypeIdentifierFacebook __attribute__((weak_import));
这意味着代码看起来像:
if (&ACAccountTypeIdentifierFacebook != NULL) {
NSLog(@"Have Facebook");
}
然后将正常工作。如果我们在示例代码的开头添加一行这样的行并编译它,我们会看到它可以毫无问题地编译,并且该符号出现在 nm -m a.out 的输出中,并且 if 测试出现在otool -tv a.out 的结果输出。