tags:

views:

85

answers:

2

I am getting errors with the linker such as:

osd.o(.ndata+0x514):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\osd.c: multiple definition of `video_buff_vis_num'
main.o(.ndata+0x0):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\main.c: first defined here
osd.o(.ndata+0x515):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\osd.c: multiple definition of `video_buff_draw_num'
main.o(.ndata+0x1):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\main.c: first defined here
osd.o(.ndata+0x516):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\osd.c: multiple definition of `vid_format'
main.o(.ndata+0x2):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\main.c: first defined here
osd.o(.ndata+0x518):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\osd.c: multiple definition of `vid_line'
main.o(.ndata+0x4):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\main.c: first defined here

This is bugging me, because in the source code I have include guards around the only place these definitions could come from.

#ifndef OSD_H 
#define OSD_H 

// code here, including definitions for the above

#endif // OSD_H 

This is getting on my nerves. I've cleaned, rebuilt, and tried again. I even started a new project from scratch with the same files and I'm getting exactly the same problem! Would anyone please enlighten me on why this isn't working! :)

Compiling with PIC-GCC v3.23 (a version of GCC for PIC24F/H and dsPIC30F/33F microcontrollers.)

Let me know if anyone wants to see the sources of more files. I didn't want to overcrowd this page.

+5  A: 

If you include this header in more than 1 .c file you will have multiple definitions. And you have main.c and osd.c.

The .h is the right place for functions and extern data declarations. But for a variable you will have to pick one of the source files. the #defined guards don't change that.

Also see this question. And this answer describes the standard pattern .

And a little more explanation/analysis:

1) Each .c source file is compiled independently. The guards only protect from reading a header file twice during 1 compile.

2) The error you are getting is a linker (not compiler) error.

When your header defines a variable, the compiler will treat it as a definition in each separate run. The linker will detect the multiple instances.

Henk Holterman
Yes, include guards won't help here.
Peter G.
So how can I avoid this problem? I have to have the definitions of osd.h in some of my files.
Thomas O
Thanks. I'll move my variables to main.c then. It would seem more fitting though to put them in osd.c, can I do that? Thanks for the fast response! I should have asked here before spending 3 hours looking through all my code. But, can I ask, why do include guards fail here? Surely OSD_H gets defined and then everything is good, it won't get included again?
Thomas O
.h is the right place to declare functions. Function implementations (except inline) should also be in .c files. @Thomas, it's included one per .c file. However, the linker then links all the resulting .o files together, which is where the problem arises.
Matthew Flaschen
@Thomas The compiler compiles each source file separately, and then links them. Include guards prevent the same header from being included twice during the compilation of a single source file, but it is still processed once for each source file that includes it (directly or indirectly).
Tyler McHenry
All appear to be variables. I do have a few inline functions. None static. Oddly, PIC-GCC never seems to inline anything... perhaps due to ROM space limitations, but that's a question for another day. Thanks everyone. I'll mark this as the accepted answer when it lets me (says I have to wait 2 minutes.)
Thomas O
You can put the variables anywhere you want, as long as they only appear in one source file. If other source files need to use these variables, they should be given an `extern` declaration for the variable, possibly in a .h file.
Tyler McHenry
A: 

What does your include file contain?

 int video_buff_vis_num;
 extern int video_buff_vis_num;

The former or the latter? The former doesn't define the variable but allocates memory for it while the latter just says "somewhere is a variable with that name".

You must have only one place where it is allocated but you can have many definitions.

Aaron Digulla