[faq] undefined reference - unresolved external

nolyc wrote:
Undefined reference is a linker error not a compile error.
You did not define the thing in the error message, you forgot to link the file that defines it, you forgot to link to the library that defines it, or, if it's a static library, you have the wrong order on the linker command line.
Check which one.
(Note that some linkers call it an unresolved external)


To understand this error, first you need to understand the build process.
Sources are not transformed directly into an executable. Instead, `object files' are created from them (compilation) and then those object files are "merged" to create the executable (linking)
This reduces the building time, because if one source was not modified, then there is no reason to reanalyze it (recompile it)

Each object files contains a list of symbols. Those symbols are the global variables and functions that its source defined, and also functions and variables that were referenced but that no definition was found during compilation. (you can list the symbols with the `nm' program.)

The linker will later fix those calls with the information given by the the other object files. However, if it does not found what a function is supposed to do, then it would complain with the `undefined reference' error.
You did not define the thing in the error message
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A{
public:
   static int value;
};

int foo(int, int);
int bar();

int main(){
   return foo(bar(), A::value);
}

int bar(int n){
   return 13;
}
That snips compiles perfectly
$ g++ -c foo.cpp
But it would fail at the linking stage
$ g++ foo.o -o program.bin
foo.o: In function `main':
foo.cpp:(.text+0xb): undefined reference to `A::value'
foo.cpp:(.text+0x10): undefined reference to `bar()'
foo.cpp:(.text+0x19): undefined reference to `foo(int, int)'
collect2: error: ld returned 1 exit status
Note that we are declaring and calling a `bar()' function that receives no argument, but the one that is defined in line 13 ask for an integer. Because the prototypes don't match they are actually two different functions.

The body for `foo()' is nowhere to be found.

Note that we are not defining the variable in line 3. We are just telling, there is a class attribute called value of type integer, but it was never created.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A{
   public:
      static int value;
};

int foo(int, int){return 0;} //providing a body
int bar();

int main(){
   return foo(bar(), A::value);
}

int bar(){ //prototypes must match
   return 13;
}

int A::value = 42; //creating the class attribute 
would build correctly
You forgot to link the file that defines it
1
2
3
4
5
6
//foo.cpp
int bar(int n);

int main(){
   return bar(42);
}
1
2
3
4
//bar.cpp
int bar(int n){
   return n*n;
}
Here we put a function definition in another file (note that the prototype is respected)
$ g++ -c foo.cpp
$ g++ foo.o
foo.o: In function `main':
foo.cpp:(.text+0xa): undefined reference to `bar(int)'
collect2: error: ld returned 1 exit status
It failed because we never tell it to look in bar.cpp for that function definition.
So the correct build process would be
$ g++ -c foo.cpp
$ g++ -c bar.cpp
$ g++ foo.o bar.o -o program.bin


If you are using an IDE, then it would be equivalent to adding the source to the project
(RTFM to know how to do it)
Last edited on
You forgot to link to the library that defines it

For our purposes libraries or objects files are equivalent. Both define symbols that we need, so we must indicate that to the linker.

Suppose that we are trying to use SFML, and are receiving this error
undefined reference to `sf::Clock::Clock()'
We figure out that the definition is in `/usr/lib/libsfml-system.so' so to build we simply do
$ g++ foo.o /usr/lib/libsfml-system.so -o program.bin


Because the file names of the libraries and the different path were they may be follow a convention, g++ provides a shortcut with the -l flag (lowercase L). So instead we could
$ g++ foo.o -lsfml-system -o program.bin


Libraries may depend on other libraries, so figuring out all the files that we need to link against may be too much work. You could use the `pkg-config' program to retrieve that information
g++ foo.o $(pkg-config --libs sfml-all)
If it's a static library, you have the wrong order on the linker command line

We say that library A depends on library B, if A has some undefined symbols for which B provides a definition.
In that case A must be before than B, so the linker can know what definitions are missing and look up them on B.

Again, the use of `pkg-config' is suggested
Templates and inline functions

This is actually an especial case of `you did not define the thing in the error message'
The code for templates is generated on-demand. So if you have
1
2
3
4
5
6
7
8
9
10
11
12
//foo.cpp
template<class T>
T min(T a, T b){
   if(a<b) return a;
   return b;
}

int main(){
   min(42,54);
   min(3.14, 2.72);
   min("hello", "world");
}
It would generate function definition for
1
2
3
char const* min<char const*>(char const*, char const*) //the reader surely found a logic issue with this one
double min<double>(double, double)
int min<int>(int, int)


However, if put the function definition in another source
1
2
3
4
5
6
//foo.cpp
template<class T>
T min(T a, T b){
   if(a<b) return a;
   return b;
}
the correspondent object file would have nothing.

The definition of a template (or inline) function must be available to all the sources that use them. Put them in the header.


There is actually possible to make foo.o contain the definition that we want. See `explicit template instantiation' http://www.cplusplus.com/forum/articles/14272/
Last edited on
Topic archived. No new replies allowed.