C++ Новичок в Linker Hell
Использование g++ и наличие ошибок компоновщика. У меня есть простая программа, разделенная на два модуля: main.cpp и кости.h кости.СРР.
Главная.cpp:
#include <iostream>
#include "Dice.h"
int main(int argc, char **argv) {
int dieRoll = Dice::roll(6);
std::cout<<dieRoll<<std::endl;
std::cin.get();
return 0;
}
Кости.h:
#ifndef DieH
#define DieH
namespace Dice
{
int roll(unsigned int dieSize);
}
#endif
Кости.cpp:
#include <ctime>
#include <cstdlib>
#include "Dice.h"
namespace Dice
{
int roll(unsigned int dieSize)
{
if (dieSize == 0)
{
return 0;
}
srand((unsigned)time(0));
int random_int = 0;
random_int = rand()%dieSize+1;
return random_int;
}
}
Я компилирую и связываю эти файлы с помощью g++ следующим образом:
g++ -o program main.cpp Dice.cpp
И я получаю следующую ошибку компоновщика:
Undefined symbols:
"Dice::roll(int)", referenced from:
_main in ccYArhzP.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Я совершенно сбита с толку. Любая помощь будет очень признательна.
3 ответа:
Ваш код хорошо сформирован.
Убедитесь, что у вас нет конфликтующих имен файлов, файлы существуют и содержат то, что вы думаете, что они делают. Например, возможно, у вас есть
Dice.cpp
, который пуст, и вы редактируете недавно созданный где-то в другом месте.Сведите к минимуму возможные расхождения, удалив ненужные файлы; есть только
main.cpp
,dice.h
, иdice.cpp
.Ваши ошибки не соответствуют вашему коду:
"Dice::roll(int)"
. Обратите внимание, что это ищетint
, но ваши функции принимаютunsigned int
. Убедитесь, что ваш заголовок совпадает.
Попробуйте следующее:
g++ main.cpp -c
Это создаст
main.o
, скомпилированный, но не связанный код для main. Сделайте то же самое сdice.cpp
:g++ dice.cpp -c
Теперь у вас есть два объектных файла, которые необходимо связать вместе. Сделайте это с помощью:
g++ main.o dice.o
И посмотреть, если это работает. Если нет, сделайте следующее:
nm main.o dice.o
Это перечислит все доступные символы в объекте, и должно дать вам что-то вроде этого:
main.o: 00000000 b .bss 00000000 d .ctors 00000000 d .data 00000000 r .eh_frame 00000000 t .text 00000098 t __GLOBAL__I_main 00000069 t __Z41__static_initialization_and_destruction_0ii U __ZN4Dice4rollEj U __ZNSi3getEv U __ZNSolsEPFRSoS_E U __ZNSolsEi U __ZNSt8ios_base4InitC1Ev U __ZNSt8ios_base4InitD1Ev U __ZSt3cin U __ZSt4cout U __ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ 00000000 b __ZStL8__ioinit U ___gxx_personality_v0 U ___main 00000055 t ___tcf_0 U _atexit 00000000 T _main dice.o: 00000000 b .bss 00000000 d .data 00000000 t .text 00000000 T __ZN4Dice4rollEj U _rand U _srand U _time
C++ искажает имена функций, поэтому все выглядит так странно. (Обратите внимание, что не существует стандартного способа искажения имен, это делает GCC 4.4).
Обратите внимание, чтоdice.o
иmain.o
относятся к одному и тому же символу:__ZN4Dice4rollEj
. Если они не совпадают, это ваша проблема. Например, если я изменю частьdice.cpp
следующим образом:// Note, it is an int, not unsigned int int roll(int dieSize)
Затем
nm main.o dice.o
производит следующее:Обратите внимание, что это дает два разных символа.main.o: 00000000 b .bss 00000000 d .ctors 00000000 d .data 00000000 r .eh_frame 00000000 t .text 00000098 t __GLOBAL__I_main 00000069 t __Z41__static_initialization_and_destruction_0ii U __ZN4Dice4rollEj U __ZNSi3getEv U __ZNSolsEPFRSoS_E U __ZNSolsEi U __ZNSt8ios_base4InitC1Ev U __ZNSt8ios_base4InitD1Ev U __ZSt3cin U __ZSt4cout U __ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ 00000000 b __ZStL8__ioinit U ___gxx_personality_v0 U ___main 00000055 t ___tcf_0 U _atexit 00000000 T _main dice.o: 00000000 b .bss 00000000 d .data 00000000 t .text 00000000 T __ZN4Dice4rollEi U _rand U _srand U _time
main.o
ищем это:__ZN4Dice4rollEj
иdice.o
содержащий это__ZN4Dice4rollEi
. (Последняя буква отличается).При попытке скомпилировать эти несовпадающие символы (с
g++ main.o dice.o
), я получаю:undefined reference to `Dice::roll(unsigned int)'
Ваша проблема заключается в том, что вы вызываете
Dice::roll(int)
и вы написали функциюDice::roll(unsigned int)
. Функция, которую он ищет, на самом деле не существует (внутренне типы аргументов функции имеют такое же значение, как и ее имя; именно так работает перегрузка). Попробуйте передать ему unsigned int (6u
, например) и посмотрите, работает ли это. Кроме того, ваш заголовочный файл может не совпадать как в файлах, так и в основном.cpp считает, что ваша функция принимает (signed) int.
Я знаю, что вы не хотите слышать ничего подобного, но "это работает для меня!".
Ваши ошибки выглядят подозрительно старыми - какую версию GCC вы используете? Это похоже на GCC 2.х! Кроме того, попробуйте ввести dieRoll в main.cpp как unsigned, что может решить проблему пространства имен на этом старом компиляторе.