У меня есть проект в Xcode (4.5.2), который прекрасно работает с использованием конфигурации Debug. Однако теперь, когда я перешел на сборку конфигурации выпуска, у меня возникает проблема: одна из моих встроенных функций сборки получает ошибку Invalid symbol redefinition
, Погуглив это сообщение об ошибке, я обнаружил несколько человек, которые получили эту ошибку компилятора, но не имеют никакой информации о том, что это означает. Вот функция с аннотированными строками ошибок:
inline int MulDivAdd(int nNumber,
int nNumerator,
int nDenominator,
int nToAdd)
{
int nRet;
__asm__ __volatile__ (
"mov %4, %%ecx \n""mov %1, %%eax \n""mull %2 \n""cmp $0, %%ecx \n""jl __sub \n""addl %%ecx, %%eax \n""adc $0, %%edx \n""jmp __div \n""__sub: \n" // "Invalid symbol redefinition""neg %%ecx \n""subl %%ecx, %%eax \n""sbb $0, %%edx \n""__div: \n" // "Invalid symbol redefinition""divl %3 \n""mov %%eax, %0 \n"
: "=m" (nRet)
: "m" (nNumber),
"m" (nNumerator),
"m" (nDenominator),
"m" (nToAdd)
: "eax", "ecx", "edx"
);
return nRet;
}
Я пытался заменить __sub
с __sbt
потому что я думал __sub
может быть защищенным именем, но это не так. Я не понимаю, почему это происходит только в Release — может ли это быть из-за оптимизации?
использование местные лейблы, такие как 1:
а также 2:
, а также jxx 1f
или же jxx 1b
, Направление прыжка (f
для форвардов или b
для назад) требуется. Итак, ваш код должен быть таким:
__asm__ __volatile__ (
"mov %4, %%ecx \n""mov %1, %%eax \n""mull %2 \n""cmp $0, %%ecx \n""jl 1f \n""addl %%ecx, %%eax \n""adc $0, %%edx \n""jmp 2f \n""1: \n""neg %%ecx \n""subl %%ecx, %%eax \n""sbb $0, %%edx \n""2: \n""divl %3 \n""mov %%eax, %0 \n")
Символы, состоящие исключительно из чисел, «локальны для функции». Поскольку «встроенный» означает, что код физически дублируется, причина, по которой вы получаете несколько определений символов, заключается в том, что ваши символы действительно определяются несколько раз «глобальным» способом.
Конечно, если у вас есть отладочная сборка, это обычно означает «нет встроенного», поэтому встроенная функция не является встроенной, символы объявляются только один раз, и она «работает».
[Я немного сомневаюсь в эффективности этого по сравнению с тем, что компилятор сделает сам — я бы подумал, по крайней мере, рассмотрение использования регистров для некоторых входных данных сделало бы его более эффективным].Других решений пока нет …