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.
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.
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.
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).
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.
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.
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 )
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With