Hi everyone,
I would like to know if something similar happen to you. Well the issue is that when I declare a variable as a global one in the header file of a module with extern sometimes it loses its value. And if I declare it as static I can not access to it from other module. As far As I understand, a static variable is the same during the all of the execution of the program and it has a space of memory reserved to it. Can anyone please clarify this?
Thanks in advance.
Hi Per,
Thanks for your help.
I have understand the issue of static variables.
I would like to know if sometimes happens to you with keil that when you declare a variable as extern to meake it global and uses it loses its value at some point of the program.I mean when I change the value of this variable and then I check if this variable has the expected value it is gone, it does not happend all the time, but it sometimes happens so I do not trust in this extern variables. Which could be the reason of this issue?
Thanks in advance for your help.
"extern" doesn't make a variable global.
Extern just tells the compiler that a variable with that name and type exists, but to not allocate any memory for it - the memory is allocated in another source file where the "extern" keyword isn't used.
No, I don't have issues with global variables losing their content.
The main reason for having variables losing their value is to have wild pointers or array index overruns. So your own code destroys other variables.
Another reason is that you have a stack overflow, in wich case the stack grows into variables.
Another reason is that you are using dynamic RAM, and haven't properly initialized the memory controller to refresh the DRAM.
Another reason is that you use DMA and have incorrect code so the DMA transfer writes to the wrong address region.
As already noted, 'extern' does not "make a variable global".
What, exactly, do you mean by, "loses its value" ?
Post a minimum example which illustrates the issue you are seeing.
... could be that you have an interrupt (or interrupts) overwriting your variable?
Or perhaps you have omitted a necessary 'volatile' qualifier so that updates don't happen (get "lost")...?
Thanks everyone for your replies,
when say global variable I meant a variable with the extern identifier in file and declared in another.For example of that:
/*********/ comm.h /********/
int aDeviceList[MAX_DEVICE_NUMBER];// I declare this variable in a header file
/**********/ main.c /*********/
extern int aDeviceList[MAX_DEVICE_NUMBER]; // then in other file I tell to the compiler that I am using this variable that is declared in another file.
And the problem is that when I am using it sometines during the program execution the value asigned to this variable in a function it is not stored in it, thus the value is gone.
So what I really want to know if it is appropriate to use extern variables to transfer values between modules and functions. And if some similar problem have happenned to you. Or if it there is a bug in Keil with thid type of variables.
I hope I have explained my self properly.
Your variable is most likely getting corrupted because your stack is too small and crashing into the statics. Suggest you look at your call tree and local variable usage and get a better idea of your stack depth. The stack is often defined in your startup_arch.s file, and could be just 1KB.
So your bug not Keil's
You should have the extern declaration in the header:
extern int aDeviceList[MAX_DEVICE_NUMBER];
And the Definition in exactly one 'C' file:
int aDeviceList[MAX_DEVICE_NUMBER];
Then other 'C' files needing to access that variable just #include the header.
c-faq.com/.../decldef.html
"So what I really want to know if it is appropriate to use extern variables to transfer values between modules and functions"
It cam be - when done properly & appropriately.
Having the definition in the header means that each 'C' file which #includes that header has its own definition.
Close, but no cigar. Having the same external, non-initialized definition occur repeatedly does open a nasty can of worms. But it doesn't mean you get multiple definitions.
An external definition without an initializer is a "tentative definition". Multiple tentative definitions of the same object are allowed inside one translation unit ... they're contracted into a single end definition and otherwise treated like declarations. I.e.
int foo[5]; int foo[5]; /*rest of source*/
is allowed, and defined to behave as if you had written
extern int foo[5]; extern int foo[5]; /*rest of source*/ int foo[5] = {0,0,0,0,0};
But the language definition only allows this within one translation unit. If you have a set of tentative definitions spread over multiple source units, you directly violate a "shall" rule of the C standard (C99 6.9 p5). That makes this undefined behaviour.
By far the most common realizations of this undefined behaviour are:
1) Linker flat-out rejects it, with an error message about a "multiply defined" symbol.
2) Merging of tentative definitions is extended across translation units; you get a single defined object in the global namespace.
I'm reasonably sure I've never seen a linker split up the set of tentatives into multiple internally linked objects, as suggested by Andy above. While that would be allowed, too, as the behaviour is, after all, undefined, it'd be a seriously nasty implementation, indeed.
"An external definition without an initializer is a "tentative definition". Multiple tentative definitions of the same object are allowed inside one translation unit"
Indeed.
"I'm reasonably sure I've never seen a linker split up the set of tentatives into multiple internally linked objects, as suggested by Andy above"
The thread title speaks of 'static'...
If you have static definitions in a header, then you will get the "multiple internally linked objects". Perhaps this is what's happening in the OP's case: he has multiple file-scope variables with the same name, and is looking at the "wrong" one - so it appears to have "lost" the value he was expecting...?
Quite unfornuately the word "static" means just enough different things in discussions about C programming (let alone C++ or Java) that its mention alone means either everything or nothing at all. Overloading 'static' to mean two such different things as "static duration" and "internal linkage" may have to be called the worst design decision in the C programming language.
The OP's code fragment shown mid-thread, which we seem to be discussing now, had no 'static'. If there had been a "static" in that header fragment, it would have collided with the "extern" in the C source, and caused a compilation error.
So while it's possible that the OP's real code (which is probably quite different from the fragments shown) contains a strategically well-misplaced "static", I'll consider that highly unlikely until confirmed by OP.
Hello!
I experienced the same behavior, but debugging the code I could see it's not that the global variable had lost its content ... (that was my first thought)
It seems like loses its scope. It is strange in a global variable right? At the beginning of the function I can manage it properly, but later in the same function can not even compare it to a value or assign its value to another variable. Strangely, if I halt there the debug and pass the mouse over the global variable, popup values are correct. But makin the next step in debug takes no effect.
I know that the variable retains its value because if I create a dummy function call it from where it fails and doing the assignment or comparison there, works fine...
In dissasembly I can see that one of the register involved has not the correct offset, so I'm focusing in optimization levels to see if i can find out where is the problem.
Please, if anyone can help...
Thank you very much in advance.
I have the same problem, did you find a solution ?
Thread dating back 5 to 6 years.
Need to look at how you are using the variables across modules, and how other things are corrupting the data. Perhaps add watch points, or monitor the memory space so you can alert as soon as it happens and instrument your code flow to focus on the responsible portions.
Check stack depth and usage.
I find that conclusion impossible. Nobody ever actually knew what the original problem was, so there's no way to know yours is the same.