C++ Newbie in Linker Hell
Using g++ and having linker errors. I have a simple program in split into two modules: main.cpp and Dice.h Dice.cpp.
main.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;
}
Dice.h:
#ifndef DieH
#define DieH
namespace Dice
{
int roll(unsigned int dieSize);
}
#endif
Dice.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;
}
}
I compile and link these files using g++ as follows:
g++ -o program main.cpp Dice.cpp
And I get the following linker error:
Undefined symbols:
"Dice::roll(int)", referenced from:开发者_JAVA百科
_main in ccYArhzP.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
I'm completely flummoxed. Any help would be greatly appreciated.
Your code is well-formed.
Ensure that your don't have conflicting file names, the files exist and contain what you think they do. For example, perhaps you have a Dice.cpp
that's empty, and you're editing a newly created one somewhere else.
Minimize possible discrepancy by removing unnecessary files; only have main.cpp
, dice.h
, and dice.cpp
.
Your errors do not match your code: "Dice::roll(int)"
. Observe that this is looking for an int
, but your functions take an unsigned int
. Make sure your header matches.
Try the following:
g++ main.cpp -c
This will generate main.o
, the compiled but not-linked code for main. Do the same with dice.cpp
:
g++ dice.cpp -c
You now have two object files that need to be linked together. Do so with:
g++ main.o dice.o
And see if that works. If not, do the following:
nm main.o dice.o
This will list all the available symbols in an object, and should give you something like this:
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++ mangles function names, which is why everything looks so weird. (Note, there is no standard way of mangling names, this is how GCC 4.4 does it).
Observe that dice.o
and main.o
refer to the same symbol: __ZN4Dice4rollEj
. If these do not match, that's your problem. For example, if I change part of dice.cpp
to be this:
// Note, it is an int, not unsigned int
int roll(int dieSize)
Then nm main.o dice.o
produces the following:
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
Note, this gives two different symbols. main.o
looking for this: __ZN4Dice4rollEj
and dice.o
containing this __ZN4Dice4rollEi
. (The last letter differs).
When trying to compile these mismatched symbols (with g++ main.o dice.o
), I get:
undefined reference to `Dice::roll(unsigned int)'
Your problem is that you're calling Dice::roll(int)
and you wrote a Dice::roll(unsigned int)
function. The function it's looking for doesn't actually exist (internally, argument types of a function matter just as much as its name; this is how overloading works). Try passing it an unsigned int (6u
for example) and see if that works. Alternately, your header file may not match in both files, and main.cpp thinks your function takes a (signed) int.
I know you don't want to hear anything like it, but "It works for me!".
Your errors look suspiciously old - what version of GCC are you using? This look like GCC 2.x! Also, try to type dieRoll in main.cpp as unsigned, that might resolve namespace problem on this old compiler.
精彩评论