Понимание происхождения дубликата символьной ошибки компоновщика

17

У меня есть c ++-программа, скомпилированная ранее, но после того, как вы удалили Jamfiles, программа больше не компилировалась, а ld выбрали duplicate symbol error . Это продолжалось после последовательного возврата к исходным файлам Jamfiles, запуская bjam clean , удаляя объекты вручную и переключаясь с clang с передним концом gcc на gcc 4.2.1 на MacOs 10.6.7.

Упрощенное описание программы состоит в том, что есть main.cpp и четыре файла, a.h,cpp и b.h,cpp , которые скомпилированы в статическую библиотеку, связанную с main.o . Оба, main.cpp и b.cpp зависят от файла, содержащего оскорбительный символ, off.h , через два разных промежуточных файла, но ни a.h , ни a.cpp никак не зависят от off.h .

Прежде чем вы спросите, я убедился, что все файлы были обернуты множеством определений ( #ifndef , #define , #endif ), и, хотя я нашел файл, который их пропускал, он не ссылался на% код%. Что еще более важно, off.h не содержит ничего, что ссылается на b.h , только реализация, off.h , ссылается на b.cpp . Это только меня озадачило.

Чтобы добавить к моей путанице, мне удалось удалить ссылку на off.h из off.h и, как и ожидалось, она перекомпилировала успешно. Однако, когда я добавил ссылку обратно, она также была скомпилирована успешно и продолжала делать это после очистки объектных файлов. Я все еще в недоумении, почему он не смог скомпилировать, особенно учитывая, что символы не должны были противоречить друг другу, я предотвратил дублирование символов, и я избавился от любых предыдущих / неполных сборок.

Поскольку я смог успешно скомпилировать свою программу, я сомневаюсь, что смогу воспроизвести ее, чтобы проверить любые предложения. Тем не менее, мне любопытно, как это может произойти, и если я буду сталкиваться с этим поведением в будущем, что, если что-либо, кроме того, что я сделал, могу сделать, чтобы исправить это?

    
задан rcollyer 24.05.2011 в 22:04
источник

1 ответ

38

Это часто является результатом определения объекта в файле заголовка, а не просто его объявления. Рассмотрим:

h.h :

#ifndef H_H_
#define H_H_
int i;
#endif

a.cpp :

#include "h.h"

b.cpp :

#include "h.h"
int main() {}

Это приведет к дублированию символа i . Решение состоит в том, чтобы объявить объект в файле заголовка: extern int i; и определить его в одном из файлов исходного кода: int i; .

    
ответ дан Robᵩ 24.05.2011 в 22:40
источник