1

我正在尝试解决如果我忘记在我的目标中包含类别实现,Xcode 可以告诉我吗?,我想出了以下解决方案:

NSObject+Foo.h

extern int volatile canary;
void canaryCage() {
  canary = 0;
}

NSObject+Foo.m

int canary = 0;

现在,如果我在一个源文件中,如果我的目标中没有包含#import "NSObject+Foo.h"链接器错误,我会得到一个链接器错误。NSObject+Foo.m

但是,每次#import "NSObject+Foo.h"我生成一个重复的_canaryCage符号。我不能使用__COUNTER__,因为我只#import "NSObject+Foo.h"在实现文件中。我需要canaryCage在我的整个符号表中是唯一的。

我需要类似的东西:

#define CONCAT(x, y) x##y
#define CONCAT2(x, y) CONCAT(x, y)
extern int volatile canary;
void CONCAT2(canaryCage, __RANDOM__)() {
  canary = 0;
}

这样,如果我有如下源文件:

巴.m

#import "NSObject+Foo.h"

巴兹

#import "NSObject+Foo.h"

我会得到类似_canaryCage9572098740753234521and的符号_canaryCage549569815492345,这不会冲突。我也不想启用--allow-multiple-definitionin,ld因为我希望其他重复的符号定义会导致错误。canaryCage除了我忘记链接我#import编辑的头文件的源文件的标记之外,我不想使用任何东西。

4

2 回答 2

2

如果你成功了static,每个翻译单元都会得到自己的副本,其他一切都应该按照你想要的方式工作——不需要预处理器体操。

static void canaryCage()
{
    canary = 0;
}
于 2013-06-13T04:35:24.490 回答
0

这个答案很接近,但它导致canaryCage被优化掉,因为它是死代码。

解决方案:

NSObject+Foo.h

extern int canary;
__attribute__((constructor)) static void canaryCage() {
  canary = 0;
}

NSObject+Foo.m

int canary = 0;

不幸的是,每次导入类别时都会增加一些开销,但开销非常小。如果有人知道防止canaryCage被剥夺的方法,我很乐意将他们的答案标记为正确。

于 2013-06-14T16:05:55.533 回答