One of the namespaces in my program is spread between two files. One provides the "engine", the other uses the "engine" to perform various commands. All of the initializations are performed on the "engine" side, including caching parameters fetched from setup library.
So, there's engine.cpp
with:
#include <stdio.h>
#include "ns.h"
namespace MyNS
{
unsigned char variable = 0;
void init()
{
variable = 5;
printf("Init: var = %d\n",variable);
}
void handler()
{
// printf("Handler: var = %d\n",variable);
}
}
The variable happens never to be used again in engine.cpp
but it's extensively used in commands.cpp
.
#include <stdio.h>
#include "ns.h"
namespace MyNS
{
extern unsigned char variable;
void command()
{
printf("Command: var = %d\n",variable);
}
}
After compiling and linking, I'm getting:
Init: var = 5
Command: var = 1
Now, if I uncomment the printf() in handler()
I'm getting:
Engine: var = 5
Command: var = 5
Handler: var = 5
What would be the "correct" way to force GCC not to optimize it away in such a way that accessing it through extern
from the other file would fetch the right value? Preferably without reducing the -O
level for the rest of the application?
(for completeness case, main.h
and ns.h
: )
#include "ns.h"
int main(int argc, char** argv)
{
MyNS::init();
MyNS::command();
MyNS::handler();
return 0;
}
namespace MyNS
{
void init();
void command();
void handler();
}
This minimized testcase doesn't exhibit this particular behavior; it seems one needs this situation to occur in much more complex environment to happen...
eh... the solution was quite trivial.
I exchanged places of the declaration and definition of the variable.
engine.cpp
:
extern unsigned char variable;
command.cpp
:
unsigned char variable = 0;
That way the compiler has no doubts about need for this variable's existence while compiling commands
and in engine
it has to reach to the existing instance, it can't just create a temporary one on the spot.
EDIT: Now I've discovered another peculiarity. The value changes depending on where it's written to. The section of code in question is:
1: varso = SharedObject::Instance()->varso;
2: memset(det_map,0,sizeof(det_map));
3: memset(gr_map,0xFF,sizeof(gr_map));
4: memset(gr_ped,false,sizeof(gr_ped));
5: memset(&stan,0,sizeof(stan));
6: stan.SOTUstage = 1;
7: PR_SOTU = varso->NrPSOTU;
The variable occurs near a place where several arrays are initialized with memset. The variable in question is PR_SOTU
(the uppercase is inherited from when it was still a macro, and since it acts along with several other macros acting in a very similar context, it's likely to stay that way).
If move the assignment from its line 7 and place it after lines 1, 2 or 3, it receives the correct value 5
. Placed after line 4 it gets the value 18
. Anything below, and the value is 1
. I moved definition of the variable to a different place (it was the last on the list of all namespace-globals, now it's first) to exclude possibility something writes at that specific memory location, but the behavior remains.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With