TheMeaningfulEngineer
TheMeaningfulEngineer

Reputation: 16319

Undefined reference error but symbol existing in the library

I get an undefined reference error for the example below. I have seen lots of questions that relate to this issue but believe I gave a stripped, reproducible, conceptual example as opposed specific issues in other questions,

dynlib.h:

void printMe_dyn();

dynlib.c:

#include <stdio.h>
#include "dynlib.h"

void printMe_dyn() {
  printf("I am execuded from a dynamic lib");
}

myapp.c:

#include <stdio.h>
#include "dynlib.h"

int main() 
{
    printMe_dyn();
    return 0;
}

Build steps:

gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
gcc -Wall -L. -ldynlib myapp.c -o myapp

Error:

/tmp/ccwb6Fnv.o: In function `main':
myapp.c:(.text+0xa): undefined reference to `printMe_dyn'
collect2: error: ld returned 1 exit status

Proof that the symbol is in the library:

nm libdynlib.so | grep printMe_dyn
00000000000006e0 T printMe_dyn
  1. Am I using the correct compiler flags for building the dynamic library?
  2. Is the proof I've presented really an unambiguous proof?
  3. What other approach could be taken to diagnose the issue?

Upvotes: 8

Views: 4594

Answers (3)

Alexey Antonenko
Alexey Antonenko

Reputation: 2627

Just as additional notice. The same behavior one may obtain when the library has been built by gcc and linked to the c++ project. Like follows:

gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
g++ -o myapp -Wall -L. myapp.cpp -ldynlib

In such case the reason is name-mangling used by g++. To have it turned off one must wrap C-function prototypes by extern "C" within C-library. For example like follows:

dynlib.h:

#ifdef __cplusplus
extern "C"{
#endif
void printMe_dyn();
#ifdef __cplusplus
}
#endif

Upvotes: 5

Sourav Ghosh
Sourav Ghosh

Reputation: 134276

The order of appearance of libraries matter.

To quote the online gcc manual

It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.

You should be changing your compilation statement to

gcc -o myapp -Wall -L. myapp.c -ldynlib 

to tell gcc to search for the symbols used in (compiled) myapp.c to be present in dynlib.

Upvotes: 5

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136208

The order of libraries in linker command line matters. Fix:

gcc -o myapp -Wall -L. myapp.c -ldynlib 

Upvotes: 1

Related Questions