Генерация случайного идентификатора в препроцессоре C, чтобы избежать дублирования символов компоновщика
Я пытаюсь решить, может ли 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;
}
Таким образом, если у меня есть исходные файлы, такие как:
Bar.m
#import "NSObject+Foo.h"
Baz.m
#import "NSObject+Foo.h"
Я получу символы как _canaryCage9572098740753234521
а также _canaryCage549569815492345
, который не будет конфликтовать. Я тоже не хочу включать --allow-multiple-definition
в ld
потому что я хочу, чтобы другие повторяющиеся определения символов вызывали ошибку. Я не хочу использовать canaryCage
для чего-либо, кроме маркера, который я забыл связать исходный файл, заголовок которого я #import
редактор
2 ответа
Этот ответ был близок, но это привело к canaryCage
быть оптимизирован, потому что это был мертвый код.
Решение:
NSObject + foo.h
extern int canary;
__attribute__((constructor)) static void canaryCage() {
canary = 0;
}
NSObject + Foo.m
int canary = 0;
К сожалению, это добавляет некоторые накладные расходы каждый раз, когда категория импортируется, но накладные расходы очень минимальны. Если кто-нибудь знает способ предотвратить canaryCage
от того, что меня раздели, я с радостью отмечу их ответ как правильный.
Если вы сделаете это static
каждая единица перевода получит свою собственную копию, а все остальное должно работать так, как вы этого хотите - никакой гимнастики препроцессора не требуется.
static void canaryCage()
{
canary = 0;
}