Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple definition and header-only libraries

Tags:

I have a C program with several c and h files. I decided to make one part of the program 'header-only' so I moved the code from c to h. Now I'm getting multiples definition problems and I have no idea why. e.g.:

main.c includes utils.h vector.c includes utils.h 

I moved everything in utils.c to utils.h (and of course removed utils.c from the project). utils.h starts with

#ifndef UTILS_H_ #define UTILS_H_  // and end with: #endif 

To be sure my guard was unique I tried changing it (e.g.: UTILS718171_H_) but it doesn't work.

Still, the compiler complains:

/tmp/ccOE6i1l.o: In function `compare_int': ivector.c:(.text+0x0): multiple definition of `compare_int' /tmp/ccwjCVGi.o:main.c:(.text+0x660): first defined here /tmp/ccOE6i1l.o: In function `compare_int2': ivector.c:(.text+0x20): multiple definition of `compare_int2' /tmp/ccwjCVGi.o:main.c:(.text+0x6e0): first defined here /tmp/ccOE6i1l.o: In function `matrix_alloc': ivector.c:(.text+0x40): multiple definition of `matrix_alloc' /tmp/ccwjCVGi.o:main.c:(.text+0x0): first defined here ... 

The problem might be something like: all c files are compiled and get their own version of the code and then at linkage it causes problem, but I have honestly no idea how to solve this problem.

like image 893
Suugaku Avatar asked Nov 20 '11 13:11

Suugaku


People also ask

What means header-only library?

In the context of the C or C++ programming languages, a library is called header-only if the full definitions of all macros, functions and classes comprising the library are visible to the compiler in a header file form.

How do you avoid multiple definitions in C++?

extern int x[]; This makes x visible, so code in other source files can access x , but only defines it in one place, so you don't violate the one definition rule, causing the linker to complain about multiple definitions.

Why are some libraries header-only?

Having a header-only library also means you don't have to worry about different platforms where the library might be used. When you separate the implementation, you usually do so to hide implementation details, and distribute the library as a combination of headers and libraries ( lib , dll 's or . so files).

Can you put definitions in header files?

Yes, that is correct. The function will be defined in every place where you include its header. The compiler will care about putting only one instance of it into the resulting program, by eliminating the others.


2 Answers

If you define your variables inside your header file and include the header in several c files, you are bound to get multiple definitions error because you break the One definition rule(ODR), which states that there should be only one definition in one Translation Unit(header files + source file).

Solution is:
You should define the entities you get Multiple definition errors for only once.
For Functions:
Declare the function prototypes in header file(which you include in other source files) and define the function in one and only one source file.
For Global variables:
You declare the variable extern in header file(which you include in other source files) and then define the variable in one and only one source file.

like image 162
Alok Save Avatar answered Sep 18 '22 02:09

Alok Save


You are missing the point of #ifndef _FOO_H / #define _FOO_H / #endif construct. That only protects against multiple inclusions in ONE file. For example they protect against this:

foo.h:

  #ifndef _FOO_H    #define _FOO_H    /* some C stuff here */    #endif /* _FOO_H */ 

foo.c:

   #include <foo.h>    #include <bar.h>    ... 

bar.h:

   #include <foo.h>    ... 

note that foo.c and bar.h both include foo.h; here the #ifdef _FOO_H / #define _FOO_H / #endif protects against that double inclusion in foo.c ( the foo.h included in bar.h doesn't redefine stuff )

Now the next part.

Why would you move function implementation from utils.c to utils.h? Also why did you decide to make it "header-only" ?

You can, depending on whether your compiler supports static inline functions do this; but even then it's NOT recommended, as more than likely, it will make your program unnecessarily bloated because chances are your util functions are quite complex and cannot be inlined anyways.

So change it back to utils.c and utils.h construct that you had before which, i presume, WAS working and enjoy the software.

like image 37
Ahmed Masud Avatar answered Sep 22 '22 02:09

Ahmed Masud