0

I have a problem with Duplicate Definition error. I have to write a constant inside an header file which is called by other files, but that error occurs and I don't know how to resolve it. I try to use an include guard, but it doesn't work.

#ifndef _DEFINE_PORTS__H___INCLUDED
#define _DEFINE_PORTS__H___INCLUDED


#define GPIO_SWPWM_PORT              GPIOB

const uint16_t GPIO_SWPVM_LEDS[12] = {GPIO_Pin_0 , GPIO_Pin_1 , GPIO_Pin_2 ,
                                      GPIO_Pin_3 , GPIO_Pin_4 , GPIO_Pin_5 ,
                                      GPIO_Pin_6 , GPIO_Pin_7 , GPIO_Pin_8 ,
                                      GPIO_Pin_10 , GPIO_Pin_12 , GPIO_Pin_14};


#endif // _DEFINE_PORTS__H___INCLUDED

Following the error (there are more like this);

Error[Li006]: duplicate definitions for "GPIO_SWPVM_LEDS"; in "C:\Andrea\Dev\stm32\ew\Debug\Obj\App.o", and "C:\Andrea\Dev\stm32\ew\Debug\Obj\AppEeprom.o" 

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Andrea
  • 89
  • 9
  • 1
    Please provide exact and complete code that can reproduce the problem. See: [mre]. Also, provide the exact error. – kaylum Feb 04 '22 at 10:18
  • 1
    Note that it is usually bad practice to define non-static variables in a header. If the header is included into multiple C files and the resulting objects are linked together then there will be duplicate definitions of the variable. That's what is likely happening here. But it's difficult to provide a specific solution as you have not given enough context. Making the definition `static` may be sufficient. – kaylum Feb 04 '22 at 10:22
  • 1
    try adding `static` to definition of `GPIO_SWPVM_LEDS` – tstanisl Feb 04 '22 at 10:46
  • Thak you all, with static const it works. – Andrea Feb 04 '22 at 10:52
  • 1
    But that is the wrong solution, as it creates the very same variable as many times as you have modules that include the header file. – the busybee Feb 04 '22 at 12:03
  • @thebusybee I understand what you say, but if this is true why no error occurs ? If it creates a multiple variable definition it should be an error during the build process. – Andrea Feb 04 '22 at 12:34
  • @Andrea but there __is__ an error in the build process: that is during the link process. The compiler cannot know because it doesn't know that the individual files will be linked together later. – Jabberwocky Feb 04 '22 at 12:38
  • @Andrea no, the compiler and linker are fine with that. Adding `static` means that you hide it from other compilarion units. As a result you can have the same hidden identifier in multiple modules. From C standard view this is perfectly legal but in 99.9% of cases it is a bad idea to do it. – Gerhardh Feb 04 '22 at 12:45
  • @Gerhardh Ok, so is there an alternative to create an array in an header file? – Andrea Feb 04 '22 at 13:26
  • 1
    The normal way is to not put that array definition into a header but only a declaration and put the definition into a C file. That is what Jabberwocky's answer shows in second part. – Gerhardh Feb 04 '22 at 13:47

1 Answers1

3

Header guards won't help here, they address only the problem of including the header file more than once in the same compilation unit (AKA .c file).

Here you define a non static variable in a header file. If you do this, all .c files that include this header file will compile cleanly, but during the linking process all these variables will be multiply defined. It's just like if you'd put a function definition into a header file.

You should either have this in your header file:

static const uint16_t GPIO_SWPVM_LEDS[12] = {......};

...or have this in the header file (which is much is much cleaner, because the const variable will exist only once):

extern const int GPIO_SWPVM_LEDS[12];

and put the variable definiton in one of your .c files:

const uint16_t GPIO_SWPVM_LEDS[12] = {......};

Read this SO article for more information:

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115