EXPORT_SYMBOL in header causes "exported twice" errors - c

I have a header file with the declaration of several global variables in the following format:
constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
extern unsigned var;
EXPORT_SYMBOL(var);
#endif
constants.c
#include "constants.h"
unsigned var = 10;
foo.c
#include "constants.h"
When I try to compile the kernel module, I get the following error for each respective exported symbol:
WARNING: /home/vilhelm/proj/constants: 'var' exported twice. Previous export was in /home/vilhelm/proj/foo.ko
I suspect that the symbols are being exported every time I include the constants.h header file, but I don't understand why. Shouldn't the include guard in constants.h prevent the EXPORT_SYMBOL(var) from being read multiple times?

Shouldn't the include guard in constants.h prevent the
EXPORT_SYMBOL(var) from being read multiple times?
The include guard prevents the header from being included more than once in the same source file. It can't prevent it from being included via multiple source files. Remember that the objects from all the sources get linked into a single object, and hence the conflict.
Let's say you have another header that is also included in the source files, called foo.h, which in turn includes constants.h. The file constants.c will try to include constants.h twice (once directly via constants.h and again via foo.h). The include guard works here, and constants.h will only be included once.
Same thing will happen with foo.c. It will try to include constants.h twice (once directly via constants.h and again via foo.h). The include guard works here too, and constants.h will only be included once.
But then the two objects, constants.o and foo.o will be linked together, each with its single copy of the EXPORT via constants.h. This adds up to two.
You want to make sure that exports appear in the final link just once. One way to do that would be to take them out of a common file like constants.h, and move them to a file called exports.c.

Related

Basic question about header file inclusion

I'm creating a new project in keil to learn how to add files and headers and link them properly. I need some help in understanding the optimised way to add header files.
I've a main.h file, in that I've included FU68xx.h, adc.h and gpio.h file.
#ifndef HEADER_FILE
#define HEADER_FILE
#include <FU68xx.h>
#include "adc.h"
#include "gpio.h"
#endif
In "adc.c" and "gpio.c" file i've included only main.h file and I'm able to compile successfully. But is this the right way to do it? is adding main.h file in all the files cause multiple inclusion of header files?
If I add the main.h file under #ifndef HEADER_FILE in the "adc.c" or "gpio.c" file, i get error while compiling about undefined identifiers.
Multiple inclusion of the same header file is not a problem (and not a noticeable compile-time increase) if each header is appropriately protected with an "#ifndef" as you did.
Note that the name you used in that "#ifndef" must be unique (different in each header file), so the name "HEADER_FILE" is not very good - it would have been better to call it with a unique name, e.g., "INCLUDED_MAIN_H" (and other header files will use other names). Alternatively, all modern compilers support the "#pragma once" command which is better than ifndef in two ways:
You don't need to invent a unique name (and risk that it's not unique)
The compiler doesn't need to read the header file until the end just to look for the "#endif" - once it sees the "#pragma once" and knows this is the second time reading the same file, it immediately stops reading it.
But even though including the same header file is not a problem, including too many headers in a file that doesn't need it is a problem - it increases compilation time, and also increases incremental compilation time: If you change a header file, and a hundred other files include it, the build system (e.g., make) will need to re-compile all of these hundred other files. So usually I would recommend that each source file (.c) should include only the minimal set of header files that it really needs - rather than include some big "main.h" that includes everything.

How to stop the inclusion of file imported in a file , the file in which the latter has been included in C

Like a.c has the code
#include "b.h"
b.h has:
#include "c.h"
c.h has:
void fun()
{
}
here i want to restrict a.c from acessing fun but I want b.h to access c.h
If file A.c includes file B.h, and file B.h includes file C.h, and file C.h contains function func - then A can call func - this is just how the language works.
What you can do instead is to move C.h's import into a B.c - which isn't included in A.c - and thus prevent the inclusion of func in A.c. But then you have to separate B into .h and .c - and compile B.c explicitly.
As John pointed out in the comments, you should add include guards to every .h file, e.g.:
#ifndef _B_H_
#define _B_H_
...
#endif
This prevents function declarations from getting reincluded. Also - it is bad practice to implement functions (e.g. int func() { }) in your .h files - instead you should include only their definition (e.g. int func();) and move their implementation to a separate .c file.
In the first place, this ...
here i want to restrict a.c from acessing fun
... has nothing in particular to do with header files or #include. If fun is defined as an external function anywhere in the program, then it can be called from anywhere else in the program, headers notwithstanding. This is merely a question of knowing the function's name and at least something about its signature. With that information, any source file can provide its own compatible declaration of the function to enable the call (and some compilers might even accept the call without a declaration).
If you want to restrict the locations from which fun() can be called (directly, by name) then declare it static, and move its definition to the (only) C source file from which you want it to be callable.
As far as ...
How to stop the inclusion of file imported in a file , the file in
which the latter has been included in C
... goes, you can't do that, strictly speaking. If a.c contains an #include "b.h" directive that is processed, and, in the context of processing that directive, b.h contains an #include "c.h" directive that is processed then the effect is to include the contents of c.h in a.c. Period.
If b.h contains an #include directive that you want to avoid being processed under some circumstances then conditional compilation directives (#if, #ifdef, #ifndef) are the way to do so. "Include guards" are a particularly common example, and as a matter of style and convention, every header should guard its body via appropriate include guards. If your c.h did that then it would resolve the duplicate function definition error you get from a.c directly including both b.h and c.h:
c.h
#ifndef C_H
#define C_H
// everything else ...
#endif
Of course, b.h should have its own include guards, too.
But even more importantly, avoid putting function or variable definitions in header files in the first place. Put only declarations into header files (and provide prototypes):
void f(void);
The actual definitions belong in regular source files (.c), and regular source files should never be #included by any other file. This is the way to share declarations of external functions and objects among translation units without inviting duplicate definitions.

Multiple application header files included error in C

I am doing a porting project implemented from INTEGRITY OS to UBUNTU. Facing compiler error as explained below. Even though not compiled in INTEGRITY OS, i think there is no errors there.
I got the root cause. I am expecting solution how i can achieve this.
main.c
#include "file1.h"
#include "file2.h"
#include "file3.h"
.
.
.
Inside all the files from
file1.h to file3.h below is there at the beginning of each file.
#ifdef INC_HEADER_FILE
#error Multiple header files included.
#endif
#define INC_HEADER_FILE
.
.
.
Above throws error while compiling
In file included from ../main.c:
../file1.h: error: #error Multiple application header files included.
# error Multiple application header files included.
^~~~~
Same error is thrown for all the files for file1.h to file3.h
If all three (or however many there are) of those header files use the same symbol INC_HEADER_FILE, then you will only be allowed to include one of them.
That's because including (for example) file1.h will set that symbol, meaning that including the next header will complain because it's already defined.
The include guard symbol is usually specific to the header file itself, such as INC_HEADER_1_FILE but it's my no means necessary - I've seen this sort of thing done when you only want one variation of a header file.
An example of that is a system I worked on for LED display devices where each header had different dimensions. These were constructed from 8x8 units but different quantities across and down. Having the LED addressing map in a header file allowed for efficiencies that weren't available with dynamic configuration and the include guard made sure we didn't try to use more than one map.
regarding the include guard for header1.h suggest:
#ifndef HEADER1_H
#define HEADER1_H
...
#endif
regarding the include guard for header2.h suggest:
#ifndef HEADER2_H
#define HEADER2_H
....
#endif
and similar for each header file.
The result is in any one compilation unit (source file.c) any specific header file can only be included once.

Multiple #ifndef statements - which one gets applied

Say I have five files: main.c, sample1.c, sample1.h, sample2.c and sample2.h, where in each of these files DEBUG_PRINTS is defined as follows:
#ifndef DEBUG_PRINTS
#define DEBUG_PRINTS 0
#endif
and the code is compiled using gcc:
gcc -Wall main.c sample1.c sample2.c -o main
Now I change the value of DEBUG_PRINTS in one file to 1. Without printing to the terminal how can you determine, which value will be applied?
Additionally, how can I define DEBUG_PRINTS locally per file - the same as using the static keyword for variables?
Each file is compiled separately. Macros from one file are not visible in any other file. Once the files are independently compiled, the resulting objects are linked together to create an executable.
#ifndef means if the macro isn't defined at all in that file before or in an header you included. In your case, it defaults to 0.
If you change DEBUG_PRINTS in that one file to 1, it will override that #define in #ifndef found in the header file. You are basically locally defining or overriding the default DEBUG_PRINTS in the imported header file to 1.
Otherwise, macros are visible only to this file or header.

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