How to prevent multiple definitions in C? - c

I'm a C newbie and I was just trying to write a console application with Code::Blocks. Here's the (simplified) code:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "test.c" // include not necessary for error in Code::Blocks
int main()
{
//t = test(); // calling of method also not necessary
return 0;
}
test.c:
void test() {}
When I try to build this program, it gives the following errors:
*path*\test.c|1|multiple definition of `_ test'|
obj\Debug\main.o:*path*\test.c|1|first defined here|
There is no way that I'm multiply defining test (although I don't know where the underscore is coming from) and it seems highly unlikely that the definition is somehow included twice. This is all the code there is.
I've ruled out that this error is due to some naming conflict with other functions or files being called test or test.c. Note that the multiple and the first definition are on the same line in the same file.
Does anyone know what is causing this and what I can do about it? Thanks!

You actually compile the source code of test.c twice:
The first time when compiling test.c itself,
The second time when compiling main.c which includes all the test.c source.
What you need in your main.c in order to use the test() function is a simple declaration, not its definition. This is achieved by including a test.h header file which contains something like:
void test(void);
This informs the compiler that such a function with input parameters and return type exists. What this function does ( everything inside { and } ) is left in your test.c file.
In main.c, replace #include "test.c" by #include "test.h".
A last point: with your programs being more complex, you will be faced to situations when header files may be included several times. To prevent this, header sources are sometimes enclosed by specific macro definitions, like:
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
void test(void);
#endif

The underscore is put there by the compiler and used by the linker. The basic path is:
main.c
test.h ---> [compiler] ---> main.o --+
|
test.c ---> [compiler] ---> test.o --+--> [linker] ---> main.exe
So, your main program should include the header file for the test module which should consist only of declarations, such as the function prototype:
void test(void);
This lets the compiler know that it exists when main.c is being compiled but the actual code is in test.c, then test.o.
It's the linking phase that joins together the two modules.
By including test.c into main.c, you're defining the test() function in main.o. Presumably, you're then linking main.o and test.o, both of which contain the function test().

You shouldn't include other source files (*.c) in .c files. I think you want to have a header (.h) file with the DECLARATION of test function, and have it's DEFINITION in a separate .c file.
The error is caused by multiple definitions of the test function (one in test.c and other in main.c)

I had similar problem and i solved it following way.
Solve as follows:
Function prototype declarations and global variable should be in test.h file and you can not initialize global variable in header file.
Function definition and use of global variable in test.c file
if you initialize global variables in header it will have following error
multiple definition of `_ test'|
obj\Debug\main.o:path\test.c|1|first defined here|
Just declarations of global variables in Header file no initialization should work.
Hope it helps
Cheers

Including the implementation file (test.c) causes it to be prepended to your main.c and complied there and then again separately. So, the function test has two definitions -- one in the object code of main.c and once in that of test.c, which gives you a ODR violation. You need to create a header file containing the declaration of test and include it in main.c:
/* test.h */
#ifndef TEST_H
#define TEST_H
void test(); /* declaration */
#endif /* TEST_H */

If you have added test.c to your Code::Blocks project, the definition will be seen twice - once via the #include and once by the linker. You need to:
remove the #include "test.c"
create a file test.h which contains the declaration:
void test();
include the file test.h in main.c

If you're using Visual Studio you could also do "#pragma once" at the top of the headerfile to achieve the same thing as the "#ifndef ..."-wrapping. Some other compilers probably support it as well ..
.. However, don't do this :D Stick with the #ifndef-wrapping to achieve cross-compiler compatibility. I just wanted to let you know that you could also do #pragma once, since you'll probably meet this statement quite a bit when reading other peoples code.
Good luck with it

Ages after this I found another problem that causes the same error and did not find the answer anywhere. I thought to put it here for reference to other people experiencing the same problem.
I defined a function in a header file and it kept throwing this error. (I know it is not the right way, but I thought I would quickly test it that way.)
The solution was to ONLY put a declaration in the header file and the definition in the cpp file.
The reason is that header files are not compiled, they only provide definitions.

Related

Why linking .cc file works in make file but linking .c file doesn't?

I'm working on a quite large Makefile from the tensorflow repo and I need to add a file link.
After quite some debugging of a link error, I found out that if my file ends with .cc, then the link error disappears, whereas when linking a .c file, the error appears (file content remains the same).
I am linking the file in a Makefile.inc file:
.
.
.
FL_SRCS := \
tensorflow/lite/vis_mi/main.cc \
myFunctions.c \ -->>>>IF I CHANGE THE FILENAME TO myFunctions.cc and link to this .cc file here, it works!!
.
.
.
# Builds a standalone binary.
$(eval $(call vis_test,vis_mi,\
$(FL_SRCS),$(FL_HDRS)))
The link error when using the .c ending ends with:
tensorflow/lite/vis_mi/main.o: In function `main':
tensorflow/lite/vis_mi/main.cc:183: undefined reference to `printMsg()'
../downloads/gcc_embedded/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/bin/ld: link errors found, deleting executable `tensorflow/lite/vis_mi'
collect2: error: ld returned 1 exit status
gmake: *** [tensorflow/lite/vis_mi/Makefile.inc:578: tensorflow/lite/vis_mi/bin/micro_speech] Error 1
The .c file code:
#include <stdio.h>
#include "myFunctions.h"
void printMsg(){
//do something here
}
And the header file:
#ifndef MYFUNCTIONS_H
#define MYFUNCTIONS_H
void printMsg();
#endif /* MYFUNCTIONS_H */
How can I include a file ending with .c? Makefiles are fairly new to me, and didn't want to include all the details, and if you need any further details from the Makefile to answer this question I'm happy to edit my post.
The name resolution for C and C++ functions is different. This is sometimes causing problem to "C" code that is also valid "C++". For example:
int foo(int x) { return x+1 } ;
The code Will create a function called 'foo' when compiled as "C", and will create a function called '_Z3fooi' when compiled as C++. Decoding the C++ name will (using c++filt) will show foo(int). The reason for the difference is that C++ support polymorphic functions (and methods), so that function names also identify the type of their parameters.
The proper solution is to decide on the language of the code. C++ and C are different language, and while it's possible to write code that will be valid for both, it will limit the ability to leverage each function abilities.
Important constraint: If a project contain both C and C++ code, it is important to remember that only functions that follow the "C" conventions can be called between the languages. This is usually implemented with extern "C" directive, and with #ifdef __cplusplus:
See more: https://www.thegeekstuff.com/2013/01/mix-c-and-cpp/ How to call C++ function from C? Call a C function from C++ code

'undefined reference to function' while trying to build a program with header that redefines function names

I'm having the exact same problem as a person that asked this question: How to hide the exported symbols name within a shared library
I decided to follow instructions given by Alexander (3rd answer) but after including a generated header to my main program in C, i get the error undefined reference to function
head.h
#define SecretFunc1 abab
application.c
#include <stdio.h>
#include "head.h"
int main(){
SecretFunc1();
return 0;
}
libdyn.c
#include <stdio.h>
int SecretFunc1(){
return 2
}
I've built the dynamic library into .so file, then after trying to build the app with:
gcc app.c -L<path> -ldyn -o sample
In function main undefined reference to abab
I don't really know what to do.
After (partial) preprocessing, your application.c would look like this:
#include <stdio.h>
int main(){
abab();
return 0;
}
This should, first of all, give you a warning, that abab is declared implicitly, which usually is not a good idea. You should declare the function (in a header file shared by application.c and libdyn.c):
int SecretFunc1(void);
When compiling to an object file, this object file will have a reference to the symbol abab.
After compiling libdyn.c to an object file, it will provide a symbol named SecretFunc1. Therefore, the linker will not match it to the reference abab in application.o.
You need to rename the function in all files using it, e.g. by including head.h in libdyn.c as well or better putting both the renaming macro and the declaration in a libdyn.h that is included in both libdyn.c and application.c.

Several doubts about (#include)ing non standard libraries

Let's suppose that I write some functions in a file, that we'll call foo.c.
This is foo.c:
int d;
typedef int bar;
int foo(int a, int b){
...
}
void boo(){
...
}
char *test(){
...
}
Now, boo is a function used only inside foo.c, while foo(), test(), d, and Bool will need to be able to get called inside other files.
In order to do that, I know that I have to create a foo.h file and write it like this:
extern int d;
extern typedef int bar;
int foo(int a, int b);
char *test();
then #include "foo.h" in the foo.c file, and whenever I want to use the types and functions defined in foo.c, I have to include both foo.hand foo.cin the file in which I wanna use foo.c functions and types.
So foo.c in the end would look like this:
#include "foo.h"
int d;
typedef int bar;
int foo(int a, int b){
...
}
void boo(){
...
}
char *test(){
...
}
Here are my questions.
Q1. Is this how you actually do it? Since foo.h is already included in foo.c, wouldn't it be sufficient to include only foo.c in the file in which I want to use its functions? Can't I just directly define the functions inside of the foo.c file, not using the foo.h file at all?
Q2. Do you actually have to put the extern in front of typedefs in the foo.h file?
Q3. Let's say that in foo.c I use some standard C libraries like string.h and math.h . Where should I include them? Directly in the foo.c file, in the foo.h file or in both? Are #ifndef instructions necessary? If so, how do you use them correctly?
Q4. After writing the foo.c and foo.h file, am I all ready to go? Like, I don't need to compile them or anything, right? I can just #include them wherever I need just like that?
Q5. Somewhere else I've read that if I want to use a custom library these are the steps that I need to follow:
define the interface (foo.h)
write foo.c #include ing foo.h
creating an object file like this gcc -o foo.o -c foo.c
including foo.h in the program in which I want to use foo.c functions
linking the object file like this gcc my_proj.c foo.o
Are these steps actually necessary? Because I haven't seen them mentioned anywhere else. Why do I only need to include foo.h in the file in which I want to use foo.c functions? What exactly is an object file?
Thanks for your time and sorry if this is a bit lengthy
Q1. Is this how you actually do it? Since foo.h is already included in foo.c, wouldn't it be sufficient to include only foo.c in the file in which I want to use its functions?
You just don't include .c files. In your case, foo.c and the other files are separate compilation units which get linked together in the end.
Q2. Do you actually have to put the external in front of typedefs in the foo.h file?
No, typedefs don't need extern.
Q3. Let's say that in foo.c I use some standard C libraries like string.h and math.h . Where should I include them? Directly in the foo.c file, in the foo.h file or in both? Are #ifndef instructions necessary? If so, how do you use them correctly?
If you need these files in the .h as well, you include them there (e. g. for types used in function prototypes). If you need them only in your .c, include them there.
Q4. After writing the foo.c and foo.h file, am I all ready to go? Like, I don't need to compile them or anything, right? I can just #include them wherever I need just like that?
You can compile them in order to get something callable. If you don't compile your program, you cannot use it. Or do I understand you wrong?
Q5. Somewhere else I've read that if I want to use a custom library these are the steps that I need to follow:
[snip]
Indeed, this is one way to go. The steps 1, 2 and 4 cannot be omitted for obvious reasons. But you can execute step 3 and 5 together by doing
gcc my_proj.c foo.c
This compiles the given files and then links them together in one call.
Why do I only need to include foo.h in the file in which I want to use foo.c functions?
That's because the resulting object file contains information for the linker about which function it needs from other object files.
What exactly is an object file?
It is what results from compiling one source file. If you link several object files together, you get a running executable.
In other words: An object file is the compiled version of a source file. It "provides" the identifiers needed by other object files, and it "requires" other identifiers provided by other files. Linking them together means that the required and the provided objects are connected in an appropriate way so that the program can run.
Example: You have a foo.c which defines the functions foo and test. Then you have a main.c which makes use of these functions and provides a function main. In the end, they are linked together and combined with the startup code which is needed to start a program and which calls main(). The points in main() where foo() and test() are called respectively are marked in a special way so that the linker can put the actual call address there.
Q1. Is this how you actually do it?
No
Since foo.h is already included in foo.c, wouldn't it be sufficient to
include only foo.c in the file in which I want to use its functions?
You should only include .h files; both in the file that defines them, and in the ones that use them. As an extra, that include should be the first one in the file that defines the functions, but in the files that use them, it should go after the rest (standard headers, other packages' headers, ...); the reason for this is to detect errors easily.
Can't I just directly define the functions inside of the foo.c file,
not using the foo.h file at all?
Usually, no. Only static inline functions should do that.
Q2. Do you actually have to put the extern in front of typedefs in
the foo.h file?
No: typedef int foobar_t;
Q3. Let's say that in foo.c I use some standard C libraries like
string.h and math.h . Where should I include them?
In the file that needs them (foo.c). Include in every file only the headers that it needs. No more; no less.
Directly in the foo.c file, in the foo.h file or in both?
foo.c
Are #ifndefinstructions necessary? If so, how do you use them
correctly?
Yes:
// foo.h
#ifndef FOO_H
#define FOO_H
Here go all the contents of foo.h
#endif /* foo.h */
Q4. After writing the foo.c and foo.h file, am I all ready to go?
Like, I don't need to compile them or anything, right? I can
just #include them wherever I need just like that?
You need to compile foo.c into foo.o (object file) and then you probably would like to do a static library (.a) or a dynamic one. You can include it wherever you want, but you will need to prepare your Makefile to do so.
Q5. Somewhere else I've read that if I want to use a custom library
these are the steps that I need to follow:
define the interface (foo.h)
write foo.c #include ing foo.h
creating an object file like this gcc -o foo.o -c foo.c
including foo.h in the program in which I want to use foo.c functions
linking the object file like this gcc my_proj.c foo.o
Are these steps actually necessary?
Yes
Because I haven't seen them mentioned anywhere else. Why do I only
need to include foo.h in the file in which I want to
use foo.c functions?
Read more about compiling and linking.
What exactly is an object file?
A compiled file. Many of them are usually linked together to produce the executable file.

#define scope in multiple files

I have a main file like so:
main_a.c:
#define MAIN_A
#include <stdio.h>
#include "shared.h"
extern int i;
int main() {
printf("i is: %d\n", i);
return 0;
}
I want to use the define in shared.h like this:
shared.h
#if defined(MAIN_A)
# define A
#endif
So I can declare a variable according to whether the main file is present or not, like this:
shared.c
#include "shared.h"
#if defined(A)
int i = 1;
#else
int i = 0;
#endif
I build it using a makefile which looks like this:
Makefile:
all : a
./a
a : main_a.o shared.o
gcc -o $# $^
%.o : %.c
gcc -c $<
However this prints
i is: 0
Now my question is: Why is it that the define seems to be lost when I compile the shared module? I know the main module is compiled first, so the define should have been resolved by the time shared.c is compiled.
One suspicion I have is that the preprocessor might get run at the start of each module build and not just at the start of the project. If this is correct is there a way of compiling more than a single module at a time to use the preprocessor as I attempt above?
Preprocessor is run for each file before it is compiled, i.e. once for main_a.c and then again independently for shared.c. When shared.c is compiled MAIN_A is undefined.
Preprocessor can't be used the way you're attempting, i.e. remembering state across compilation units.
What you can do is define a name (for example MAIN_A) using the -Dcompiler option in your Makefile and test this name using preprocessor the same way you're doing it now. This way the definition takes place on the project level (in the Makefile) rather than on a compilation unit level (in a .c file).
Let me do the preprocessor's work here and expand all your macros. In main.c, MAIN_A is defined, so A is defined. Nothing depends on A in main.c, and i is extern.
In shared.c, MAIN_A and thereby A are undefined, and i is 0.
In short, the preprocessor cannot transport information between compilation units. That's good practice, because otherwise programs would quickly become unreadable and you would have to recompile all compilation units when one unit changes (because symbols might have changed). Resolve the issue by setting i explicitly in main:
int main() {
i = 1;
}
It is more verbose, but is also much clearer to the reader. If you want to encapsulate, define a function InitializeShared. If you truly want to compile some code as a single compilation unit, make one of the files a header file and #include it into the other.
Yes you are right, they are completely separate compilation units.
MAIN_A is only defined in main_a.c
One thought that comes to mind is to cat the files together to make one compilation unit?
Global define A
gcc main_a.c shared.c -DA
Defines almost work the same as any variable. If you want to share a variable across modules, you put it in a header. Same goes for #defines.
However, it is strange to use the #ifdef as you are always going to have main.c. You don't want to change the code each time you compile. Instead, use the method described by Adam Zalcman

Why aren't my compile guards preventing multiple definition inclusions?

I have a header file x.h which is included by more than one *.c source files.
This header file has some structure variables defined.
I have put multiple inclusion prevention guard at the beginning of the header file as:
#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.
#endif//X_H
On building I get linker errors related to multiple definitions. I understand the problem.
Won't a multiple inclusion prevention guard at the top of header file as I have, prevent multiple inclusions of the header file x.h and thereby avoid multiple definitions of the variables that are there in x.h?
#pragma once does not work on this particular compiler, so what is the solution?
Someone had posted this answer to a similar question. It doesn't seem to work for me. How does this solution work?
If the linker is complaining, it means you have definitions rather than just declarations in your header. Here's an example of things that would be wrong.
#ifndef X_H
#define X_H
int myFunc()
{
return 42; // Wrong! definition in header.
}
int myVar; // Wrong! definition in header.
#endif
You should split this into source and header file like this:
Header:
#ifndef X_H
#define X_H
extern int myFunc();
extern int myVar;
#endif
C Source:
int myFunc()
{
return 42;
}
int myVar;
Header guards are only good for a single compilation unit, i.e., source file. If you happen to include a header file multiple times, perhaps because all headers included from main.c in turn include stdio.h then guards will help.
If you have the definition of a function f in x.h which is included by main.c and util.c, then it is like copying and pasting the definition of f into main.c when creating main.o and doing the same for util.c to create util.o. Then the linker will complain and this happens despite your header guards. Having multiple #include "x.h" statements in main.c is possible of course because of these guards.
Using include guards prevents one compilation unit from including the header twice. E.g. if header B.h includes A.h and B.cpp includes A.h and B.h, everything from A.h would be declared twice in the compilation B.cpp if you weren't using include guards.
Your include guards prevent this from happening, all's fine till now.
But you get multiple definitions at link time, i.e. two compilation units define the same thing, this probably means you got a real definition in your header, use extern for all variables, make sure functions are either inline or are defined in the cpp file.
If the functions aren't large, you can use "inline" before them and the linker won't complain.
Using a multiple inclusion guard prevents compiler errors, but you're getting a linker error. Do you have data definitions in the header file that don't use extern?
Maybe X_H is already defined somewhere else? I just ran into this issue, where Xlib defines X_H in /usr/include/X11/X.h.
To check, you can call gcc -dM -E (if you are using gcc), e.g. in the buildsystem I’m using that works with CC=gcc CFLAGS="-dM -E" make. If the output file contains #define X_H even though you remove it from your file (use Y_H for example), then it is already defined outside your source code.

Resources