Multiple definition of 'initialize_idt' - c

In the same line I get two errors:
/path/idt.c:15: multiple definition of 'initialize_idt'
and
/path/idt.c:15: first defined here
and I'm baffled as to why this might be. I'm declaring in the .h, defining in the .c, and calling in another .c. Every example I've seen doesn't properly #include, but I don't see a problem in my implementation.
/***idt.c***/
#include "idt.h"
#include "x86_desc.h"
void initialize_idt(){
//code
}
/*********/
/***idt.h***/
#ifndef _IDT_H
#define _IDT_H
#include "types.h"
void initialize_idt(void);
#endif
/*********/
/***kernel.c***/
#include "idt.h"
#include "x86_desc.h
void entry(){
initialize_idt();
}
/*********/
EDIT:
The code is very long, it would be a lot to post all at once. I tried changing _IDT_H to a long random sequence and that doesn't seem to fix the problem. grep -rnwe 'initialize_idt' returns:
idt.c:7:/* initialize_idt adding this to fix highlighting->*/
idt.c:15:void initialize_idt(){
idt.h:14:void initialize_idt(void);
Binary file idt.o matches
kernel.c:141: initialize_idt();
Binary file kernel.o matches

Related

Different macro based on where file is included

I have a master.c and slave.c file. Both are compiled seperately, producing different contiki-ng modules.
As they both use a similar function, I created a helpers.h and helpers.c file, and added #include "helpers.h" to main.c and slave.c to deduplicate this function.
Additionally, I need to use the LOG_INFO function from log.h for logging in both slave.c/master.c and in helpers.c. log.h requires the macro LOG_MODULE to be set to the name of the Module (Master or Slave).
master.c:
#define LOG_MODULE "Master"
#include "sys/log.h"
#include "helpers.h"
void main() {
do_something();
}
slave.c:
#define LOG_MODULE "Slave"
#include "sys/log.h"
#include "helpers.h"
void main() {
do_something();
}
helpers.h:
void do_something();
helpers.c:
#include "sys/log.h"
#include "helpers.h"
void do_something() {
...
LOG_INFO("Result: x");
...
}
My problem is the following:
Even though I include "helpers.h" AFTER defining LOG_MODULE in master.c/slave.c, I still get a complaint about LOG_MODULE not being defined when I use LOG_INFO in helpers.c.
What is a proper and elegant solution to define LOG_MODULE with their respective values in slave.c and master.c, and have that definition used by helpers.c?
The helpers.c is a separate compile unit and during the compilation of it, it only "sees" the #define's in the headers included only in that file.
To achieve what you what you want, you would need to:
Move the definition of all the functions that use logging from .c to .h file.
Make the logging functions inline in this header to prevent linking problems if master.c and slave.c are then linked together to create a single binary.
helpers.h
#include "sys/log.h"
inline void do_something() {
...
LOG_INFO("Result: x");
...
}

C header file is causing warning "ISO C requires a translation unit to contain at least one declaration"

Using Qt Creator I made these plain C files just to test my understanding:
main.c
#include <stdio.h>
#include "linked.h"
int main()
{
printf("Hello World!\n");
printf("%d", linked());
return 0;
}
linked.h
#ifndef LINKED_H_
#define LINKED_H_
int linked(void);
#endif // LINKED_H
linked.c
int linked()
{
return 5;
}
The IDE shows a warning on the line of linked.h in-between #define LINKED_H_ and int linked(void); which reads
ISO C requires a translation unit to contain at least one declaration
My best guess about what this means is that any header or other C file, if it is in a project, should get used in the main file at least once somewhere. I've tried searching the warning but if this has been answered elsewhere, I'm not able to understand the answer. It seems to me I've used the linked function and so it shouldn't give me this warning. Can anyone explain what's going on?
The program compiles and runs exactly as expected.
I think the issue is that you don't #include "linked.h" from linked.c. The current linked.c file doesn't have any declarations; it only has one function definition.
To fix this, add this line to linked.c:
#include "linked.h"
I don't know why it says this is an issue with linked.h, but it seems to be quite a coincidence that the line number you pointed out just happens to be the line number of the end of linked.c.
Of course, that may be all this is; a coincidence. So, if that doesn't work, try putting some sort of external declaration in this file. The easiest way to do that is to include a standard header, such as stdio.h. I would still advise you to #include "linked.h" from inside linked.c, though.
add a header
#ifndef LINKED_H_
#define LINKED_H_
#include <stdio.h>
int linked(void);
#endif // LINKED_H
The way you wrote the code, you need to use:
extern int linked(void);
(notice the additional "extern"). That might help with the issue.
Also, the code in linked.c should be:
int linked(void)
{
return 5;
}
(Notice the "parameter" - "void").
According to IBM, you need some declaration in the header file, but you do have one. Perhaps LINKED_H_ is defined elsewhere, or the compiler is seeing that it's possible that the precompiler condition might result in an empty parse.
Perhaps this header file will work for you:
linked.h
#ifndef LINKED_H_
#define LINKED_H_
int linked(void);
#endif // LINKED_H
char __allowLinkedHToBeIsoCCompliant = 1;

Standard libraries included multiple times over several files?

In the K&R book (p59) (edit: second edition, covering ANSI C), it is suggested that it is easier to split larger projects into multiple files. In each file, several libraries are included at the top as usual: e.g. getop.c needs stdio.h, and so does stack.c and so does main.c.
The snippets are something like this:
//main.c
#include <stdio.h>
#include <stdlib.h>
#include "calc.h"
int main(void)
{
//etc
}
//getop.c
#include <stdio.h>
#include <ctype.h>
#include "calc.h"
getop()
{
/*code*/
}
//stack.c
#include <stdio.h>
#include "calc.h"
void push(double val)
{
//code
}
I am having trouble figuring out how including the standard libraries several times in a project works. Of course, for the custom .c files to be able to access built in functions, we need to include #include <header.h> so that they are aware of the existence of printf() and getchar() and so on, but wouldn't this approach increase the size of the final program if stdio.h is included four times instead of once ( if everything was placed in one file)?
K&R does point out that splitting a program over several files eventually makes it more difficult to maintain all the .h files.
I suppose what I am really asking is how does the compiler figure out the problem of one library being #included several times in a project.
I have read up on using include guards, but it seems that is not needed for this implementation, as they deal with ensuring that identical bits of code aren't included twice, as in:
File "module.h"
#ifndef MODULE_H
#define MODULE_H
struct foo {
int member;
};
#endif /* MODULE_H */
File "mod2.h"
#include "module.h"
File "prog.c"
#include "module.h"
#include "mod2.h"
refs
I suppose what I am really asking is how does the compiler figure out the problem of one library being #included several times in a project.
you don't include a library by #include <stdio.h>, you just include it's declarations, so the compiler knows what functions exists. The linker takes care of including a library and putting everything together.
Because they use something called include guards, suppose your own include files where to be included more than once, then you can do this
MyHeader.h
#ifndef MY_HEADER_H
#define MY_HEADER_H
/* file content goes here */
#endif /* MY_HEADER_H */
Then you have another header
**AnotherHeader.h**
#ifndef MY_ANOTHER_HEADER_H
#define MY_ANOTHER_HEADER_H
#include "MyHeader.h"
/* file content goes here */
#endif /* MY_ANOTHER_HEADER_H */
and in your program
main.c
/*
* MY_HEADER_H is undefined so it will be defined and MyHeader.h contents
* will be included.
*/
#include "MyHeader.h"
/*
* MY_HEADER_H is defined now, so MyHeader.h contents will not be included
*/
#include "AnotherHeader.h"
int main()
{
return 0;
}
Since the included files are only included once per compilation unit the resulting binary size will not increase, besides the inclusion of header files only increases the compiled file size when for example there are string literals declared in those headers, otherwise they only provide information to the compiler about how to call a given function, i.e. how to pass parameters to it and how to store it's returned value.

How to handle multilevel includes in C?

I have second level include that is giving me grief:
Undefined first referenced
symbol in file
function2 /var/tmp//ccAPaWbT.o
ld: fatal: symbol referencing errors. No output written to run
collect2: ld returned 1 exit status
Main file:
#include "functions02.c"
int main(){
int x = funcion2();
}
functions02.c file:
#ifndef FUNCTIONS02_C
#define FUNCTIONS02_C
int funcion2();
#if __INCLUDE_LEVEL__ == 0
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "functions01.c"
int main() {
return function2();
}
#endif
int function2()
return function1();
}
#endif
functions01.c file:
#ifndef FUNCTIONS01_C
#define FUNCTIONS01_C
int funcion1();
#if __INCLUDE_LEVEL__ == 0
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main() {
return function1();
}
#endif
int function1()
return 10;
}
#endif
I am assuming that this can be fixed manipulated using __INCLUDE_LEVEL__ or manipulating linking on gcc compiling but I can't find forking variant.
First of all is it possible to achieve what I am looking for without putting functions in external header files?
Second what would be the correct way of doing it?
EDIT:
I realized that I had forgotten to add function dependencies to them. That is the includes which are used by functions can not be excluded by adding them just next to main function warped in exclusion if close.
Yes, it is possible to include / exclude any part of the code using compile time flags (and in the code using #if's) as you are trying to do.
In your case, I assume you have not defined __INCLUDE_LEVEL__ flag, hence the linker is not able to find funciton2, so the error.
If you define it, you will have three "main()" :-), it will fail again. So, you need to rework your code a bit.
Also, #include'ing a "C" file is not advisable and not used in practice. I assume you are just trying to experiment & learn, which is fine.

help with header files in C

Ok, I have a pretty good understanding of how header files are to be used in C programs but I keep having this problem that I can't seem to get around. Here is the situation:
Device.c contains #include "Device.h"
Device.h contains a definition for a struct and the following...
#ifndef DEVICE_H
#define DEVICE_H
#include "SubDevice.h"
typedef struct {
subDevice * subDevice1;
subDevice * subDevice2;
} device;
#endif
SubDevice.c contains #include SubDevice.h
SubDevice.h contains the definition of the subDevice struct and the following...
#ifndef SUBDEVICE_H
#define SUBDEVICE_H
#include "Device.h"
typedef struct{
int MyInt;
double MyDouble;
}subDevice;
#endif
The problem is that I get a compiler error in Device.h in my struct definition. At the line subDevice * subDevice1; it says syntax error before subDevice.
Is the problem that I am including the header file of the other file in each file? I thought the #ifndef - #define statements would prevent that from causing a problem...
It's not a header problem. There is a problem on one typedef you have in SubDevice.h. So, do change:
typedef struct{
int MyInt;
double MyDouble;
}
To:
typedef struct{
int MyInt;
double MyDouble;
} subDevice;
Your problem should be gone.
You must put a semicolon after the declaration of a struct, and your typedef is missing the second parameter.
EDIT to reflect OP's edit
You're including DEVICE_H, which is an macro.
You need to include "device.h":
#include "device.h"
The problem is that you have a circular reference.
I guess your main file looks something like this:
#include "Subdevice.h"
#include "Device.h"
int main() {}
Because of how the C preprocessor works (and how you use the include guards), the contents of Device.h will be read before Subdevice.h, meaning that the subDevice struct has yet to be defined when you define the device struct.
Remove the #include "Device.h" from Subdevice.h and it should compile OK.
You have "typedef struct {...}" in your subdevice.h, when you should have "typedef struct {...} subDevice;"
The line "#include DEVICE_H" also looks somewhat wrong. Did you mean #include "device.h"?
What you seem to be missing is a good understanding of the compilation model used by C (and C++) compilers.
Compiling a C or C++ source file can be separated in three stages:
Preprocessing
Compiling
Linking
Preprocessing
During preprocessing, the compiler (or separate preprocessor) goes over the source file and performs macro expansion and #include replacements.
All #include directives are replaced by the contents of the referenced file.
All macro definitions are processed and where a macro invocation occurs in the text, it is substituted with the replacement text. This is a completely textual process.
After preprocessing, there are no preprocessor directives (lines starting with a #) left in the source code
Compiling
During compilation, the compiler interprets the source code according to the rules of the C (or C++) language and translates the code to object code.
Linking
During the linking phase, all object files are combined together and linked with the relevant libraries to create an executable.
The source code presented here has two problems:
The subdevice.h file contains a spurious #include DEVICE_H directive. This should be reported by the preprocessor/compiler, because DEVICE_H does not resolve to a filename in quotes or angle-brackets.
There is a missing semi-colon (;) (and a missing typedef name) at the end of the typedef in subdevice.h. As a result, the compiler tries to combine this with the next lines of code it sees (the typedef struct in device.h) and gets terribly confused. This triggers the syntax error message.
One good way of debugging your code with preprocessor errors is to gcc -E <files>, so that you can actually see what would your program look like after that preprocessor is done with it.

Resources