Un-named struct problem

Today I spent hours chasing a bug which in the end turned out to have a simple solution (the usual story :slight_smile: ). Having found it, I've reduced the code to a fraction of what it was, to show the problem. It's all to do with defining (not declaring) an unnamed struct in a header file.

So, in 'header.h' I had something like this:

struct {
  int value;
} definedInHeader;

Now, I know that's not good, the struct should be declared in the header and defined elsewhere. I had copied the struct code from someone else's cpp file (that didn't use a header) and moved it into a header carelessly. That header was then #included in two different .cpp files. The result was very strange things happening to the values of the contents of my struct.

Here's my full header for the simplified code:

// header1.h

#ifndef _HEADER1_h
#define _HEADER1_h

struct {
  int value;
} definedInHeader;

void incrementIt();

#endif

Here's my simplified .cpp file:

#include "header1.h"

void incrementIt() {
  definedInHeader.value += 1;
}

and here's my main .ino file:

#include "header1.h"

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(100);
  definedInHeader.value = 2;

}

void loop() {
  // put your main code here, to run repeatedly:
  incrementIt();
  Serial.println(definedInHeader.value);
  delay(1000);

}

which (of course) just prints '2' continuosly, rather than incrementing the value.

So, my question is, why doesn't the linker tell me that I have multiple defintions? If I had done this instead, and named the struct:

struct myStruct {
  int value;
} definedInHeader;

then the linker correctly tells me I have "multiple definition of `definedInHeader'"

Is this normal in C / C++ or just a bug in the linker?

Excellent. A puzzle. There are definitely two instances of definedInHeader.

I suspect it has to do with the fact that, in C++, struct and class are interchangeable and that class / struct is a type definition. In each compilation unit you are defining a new anonymous class (type) with a single instance. I suspect a name is synthesized for the class and instance.

We need to see the mangled name.

And, here they are...

0080011f l     O .bss   00000002 definedInHeader.lto_priv.13
0080011d l     O .bss   00000002 definedInHeader.lto_priv.12

Add a class name and provide a single definition...

0080011d l     O .bss   00000002 definedInHeader

So, the answer is "no"; the linker is not buggy. The C++ language has a few rough spots and you just happen to cross paths with one.

When you make an un-named struct, the compiler will "name" it when it compiles. So your 2 structs will have name A, B (may or may not be actual names) respectively. So there will not be error because they have completely different names.

arduino_new:
So your 2 structs will have name...

definedInHeader.lto_priv.13 and definedInHeader.lto_priv.12. My post includes the actual names. Using hypothetical names is unnecessary and confusing.