Pointer to a global static variable - not safe? - c

I have file in which I have a global array
static char name[6];
and a function
static char* gen_name(char* dest, const size_t len) {
for (int i = 0; i < len - 1; ++i)
dest[i] = 'A' + (genrand_uint32() % ('Z' - 'A'));
dest[len - 1] = '\0';
return dest;
}
The pointer to the name is then stored in a global variable in different header file, this variable is not static.
this_name = gen_name(name, sizeof name);
When a function in another file uses this pointer, it works well on Linux, but when I run the same code on a microcontroller, it prints garbage.
When I remove the static keyword, it works fine.
Why is this happening?
When should I use static?
I thought I should declare all variables and functions that are not used outside of a file as static, is this wrong?

When you declared the variable in the header, did you remember to mark it extern? You need to do that, otherwise what happens is that you just get a new variable in each file that includes the header. Remember that #include is just a copy&paste job; the preprocessor just inserts the text from the header file in the location where the include happens. If the text in the header file is char name[6], then that's just what you get; text in your source that says char name[6], resulting in a variable name that has nothing to do with the variable that you have in your other source file.
If you mark it as extern, the linker will then complain that the symbol was not found. That means the definition of name can't be static, as that causes the linker not being able to find it.
So, in your header file, you need this declaration:
extern char name[6];
and in your source file, you need this definition:
char name[6];
And to answer the actual question: yes, it's perfectly safe.

It turned out to be caused by a stack overflow in a different thread, marking it static would put it in the bss section, just behind the stack that would overflow.

Static keyword means different things to functions and variables.
Functions are by default 'extern', i.e. their entry points are made public by the compiler so the linker can find them and they can be called from any compiled module.
If you put 'static' in front of a function's declaration, the function will stop being public, i.e. it will only be known inside the same source module.
'static' keyword has very different meaning when used for variables(*). It makes them non-changeable.
When you say 'static char name[6]', you are telling the compiler that you have no intention of changing value of 'name'.
On Linux running on a PC, this doesn't mean much. You tell the compiler that you won't change the value and then you change it. You lied. No big deal.
Some microcontrollers have internal flash that they can use to run code from, and keep fixed (constant!) data in.
The compiler and linker use your promise that 'name' will not change and leave the variable in the flash memory.
You can imagine what (doesn't) happen when you try to change it.
More precisely, the compiler will place all your static variables in something like .const section, and linker will then place that section in flash memory.
(*) There is a way to look at 'const' that makes it having the same meaning when used for variables as for functions. Not important here.

Related

How global and local with same static variable names stored in C internally memory?

#include<stdio.h>
static int a=5;
main()
{
static int a=15;
printf("%d\n",a);
}
So, how are both variables a stored in internal memory?
How are global and local variables with the same variable names stored internally in memory?
#include<stdio.h>
static int a=5;
int main()
{
printf("%p\n",(void *)&a);
static int a=15;
printf("%p\n",(void *)&a);
return 0;
}
Output for the upper program is
0x564e6b67a030
0x564e6b67a034
So you can see that both are stored in different addresses. As one is a global variable and other is local.
The names are only of interest to the human reader and the compiler/linker translating that code to machine executable code. The final object code resolves these to addresses and the names no longer exist.
The compiler distinguishes these the same way you do - by scope; when two identical symbols in the same namespace are in scope simultaneously, the symbol with the most restrictive scope is visible (i.e. may be accessed via the name).
For symbols with external linkage (in your example there are none other then main), the compiler retains the symbol name in order to resolve links between separately compiled modules. In the fully linked executable the symbol names cease to exist (except in debug build symbol meta-data).
The thing is the scope don't let them mess up. The first one has file scope and the other has block scope. (They are different variables - they are stored in separate memories.)
When you use it in the block - compiler checks whether this reference is resolved by anything in the same block. It gets one. And done.
And in case it is in some other function - if it doesn't find anything named a - the search ends in file scope where it finds the name a. That is where the story ends.
Both being static their storage duration is same. They live till the program exists. But their scope is different. If the scope was same too - compiler would have shown you error message.
Here if you compile with -Wshadow option - it will warn you about shadowing a variable. You shadowed the outer a with the inner on that block. That's it.
The facetious answer is that they are stored in different places.
Remember that the names of variables do not (normally) form part of the compiled program, so the compiler just follows the normal rules of variable shadowing. So in your case your print function (that's not a standard C function by the way - did you mean printf?) outputs the a declared in main. The fact that you've used the same name will not bother the compiler at all.
Finally C provides no way of accessing the global scoped a once the other declaration is encountered in main as it's static. (It is wasn't static you could use extern.) See How can I access a shadowed global variable in C?

Uninitialized variable put into program memory area. AVR programming

In xxx.h file I have declaration:
const struct MenuItem MenuItemA;
in xxx.c file I have definition:
const struct MenuItem MenuItemA PROGMEM = {textA, MenuItemAFunction, &MenuItemB, 0};
I also include xxx.h file in my main.c file.
While building the project i get this warning:
uninitialized variable 'MenuItemA' put into program memory area [-Wuninitialized]
When I had declaration and definition in the same .c file everything was OK, I have no idea what is wrong now.
Joachim is correct, ALL definitions in header files need an extern - otherwise every time you use the header (in a different source file) you'll create another copy of the variable.
To answer your original question, I suspect the variable is in the code section because it is constant, if you remove the const it'll go into the BSS or DATA section depending on how it's defined.
But you're main problem is the lack of an extern
As you say, it is not an error, but merely a warning about wasting precious flash memory for uninitialized variables.
If it is indeed uninitialized, there seems to be no need to put it explicity into progmem as it is constant there and cannot be overwritten (easily) during program run.
The way you use it - have a tentative definition in all files which include the header file and define it in one file will make the compilation of the other files complain about exacly this. (This would better be a link time warning instead of a compile time warning...)
(BEGIN of long BLAH)
I just ran into the same issue: I want to create a "plugin" framework where the user of my library can choose whether to add a certain function pointer as a "plugin": in my library's header file, I have a
extern some_type * const PROGMEM my_array[];
and a
#define enable_my_stuff() some_type * const PROGMEM my_array[2] = {something_of_some_type, NULL}
while my library's C file has a
// Tentative definition which is used when nothing else is there.
some_type * const PROGMEM my_array[2];
This way I have two cases: either no one uses enable_my_stuff() and my array is empty (that's ok, but 4 bytes are wasted) or enable_my_stuff() is used, the extended functionality is activated and the array content reflects this.
It works, but I get exactly the warning as above. As it annoys me, I'm probably going to implement it in a different way.
(END of long BLAH)

Just want to make sure I'm understanding what an external variable is

For our assignment we have to code a program in C, but it says not to use external variables in the program. Does this mean variables in other files brought into the main code, or am I unable to use variables in the same file if they're not in the same function? (ie: could I pass a value into a function as an argument and have it return a value that may have to do with a variable in that function and set the return value equal to something, or is that using external variables?)
I've Googled around but it's not exactly clear, and I want to make sure, as this is rather important.
Just to be sure, I'd make all my variables part of a function, and either pass them as parameters or return them from the functions.
There are at least two interpretations of external variables.
First off, we have the extern keyword, which basically symbolizes what you would call a global variable. It's a variable declared in multiple translation unit, but it only exists in one place in memory. It is initialized in a single file and all subsequent changes affect every scope the variable is used in:
//globals.cpp
int x = 1337;
//main.cpp
extern int x;
int main()
{
//x is 1337 here
return 0;
}
The second meaning could be a variable that is declared and defined in class scope, but not used as extern. However, you could consider it external to the methods.
//main.cpp
int x = 1337; //is this external?
//could be, remove it just to be safe
int main()
{
return 0;
}
Let's go with all the possible cases, because from your question I'm not too sure either:
There is extern as a keyword. In order to understand this, you need to understand compilation units. Basically, each file is a compilation unit - so each .c is compiled to a .o with the headers substituted in place. In each compilation unit, you forward declare symbols you expect to use - functions belonging to other compilation units, for example.
Now, if you declare a global variable in one .c file, it is global wrt that file, but does not exist as a symbol in any other file at all - the compiler will error because it doesn't know where that variable was declared.
(Of course, if you declare the variable in a header - it will exist in all of the objects the header is included in, and then the linker will sulk, because when it links all the objects up some of the symbols will have the same name).
To get around this, it is possible to define a variable with extern int x;, for example. This tells the compiler a) int x should be available to this compilation unit, b) int x is not in this compilation unit and c) the linker should check it exists somewhere in all the units you've put together to form a library or program.
Conceptually, you're doing this all the time with forward-declarations of functions. There's just no way to forward declare a variable. In fact, you can do this with functions too and not bother r.e shared headers, although this is not really a good idea.
The other case is that "external variables" mean something external to a certain scope or module you have. I would check your assignment very carefully and if in doubt ask - whoever set it should be able to explain to you exactly what they mean.
An external variable is a variable with external linkage.
A variable with external linkage is a variable defined at file scope without the static keyword.
int bla = 0; // external variable
static int blop = 1; // non-external variable
int main(void)
{
return bla
}
Note that a variable declared with the extern keyword doesn't necessarily have external linkage. Like const does not mean constant in C, extern does not mean external.
People often use the word external to say that a variable is actually declared in the current translation unit but is defined in another translation unit.

Printing Environmental variables in Linux

I am new to Linux. I came across this piece of code to print environmental variables. It is kind of confusing me. How can this code print the environmental variables?
#include <stdio.h>
extern char **environ;
int main()
{
char **var;
for(var=environ; *var!=NULL;++var)
printf("%s\n",*var);
return 0;
}
what is extern here?
If you don't know what extern means, please find a book to learn C from. It simply means 'defined somewhere else, but used here'.
The environ global variable is unique amongst POSIX global variables in that it is not declared in any header. It is like the argv array to the program, an array of character pointers each of which points at an environment variable in the name=value format. The list is terminated by a null pointer, just like argv is. There is no count for the environment, though.
for (var = environ; *var != NULL; ++var)
printf("%s\n", *var);
So, on the first iteration, var points at the first environment variable; then it is incremented to the next, until the value *var (a char *) is NULL, indicating the end of the list.
That loop could also be written as:
char **var = environ;
while (*var != 0)
puts(*var++);
From wikipedia http://en.wikipedia.org/wiki/External_variable:
Definition, declaration and the extern keyword
To understand how external variables relate to the extern keyword, it is necessary to know the difference between defining and declaring a variable. When a variable is defined, the compiler allocates memory for that variable and possibly also initializes its contents to some value. When a variable is declared, the compiler requires that the variable be defined elsewhere. The declaration informs the compiler that a variable by that name and type exists, but the compiler need not allocate memory for it since it is allocated elsewhere.
The extern keyword means "declare without defining". In other words, it is a way to explicitly declare a variable, or to force a declaration without a definition. It is also possible to explicitly define a variable, i.e. to force a definition. It is done by assigning an initialization value to a variable. If neither the extern keyword nor an initialization value are present, the statement can be either a declaration or a definition. It is up to the compiler to analyse the modules of the program and decide.
A variable must be defined once in one of the modules of the program. If there is no definition or more than one, an error is produced, possibly in the linking stage. A variable may be declared many times, as long as the declarations are consistent with each other and with the definition (something which header files facilitate greatly). It may be declared in many modules, including the module where it was defined, and even many times in the same module. But it is usually pointless to declare it more than once in a module.
An external variable may also be declared inside a function. In this case the extern keyword must be used, otherwise the compiler will consider it a definition of a local variable, which has a different scope, lifetime and initial value. This declaration will only be visible inside the function instead of throughout the function's module.
The extern keyword applied to a function prototype does absolutely nothing (the extern keyword applied to a function definition is, of course, non-sensical). A function prototype is always a declaration and never a definition. Also, in ANSI C, a function is always external, but some compiler extensions and newer C standards allow a function to be defined inside a function.
An external variable must be defined, exactly once, outside of any
function; this sets aside storage for it. The variable must also be
declared in each function that wants to access it; this states the
type of the variable. The declaration may be an explicit extern
statement or may be implicit from context. ... You should note that we
are using the words definition and declaration carefully when we refer
to external variables in this section. Definition refers to the place
where the variable is created or assigned storage; declaration refers
to places where the nature of the variable is stated but no storage is
allocated.
—The C Programming Language
Scope, lifetime and the static keyword
An external variable can be accessed by all the functions in all the modules of a program. It is a global variable. For a function to be able to use the variable, a declaration or the definition of the external variable must lie before the function definition in the source code. Or there must be a declaration of the variable, with the keyword extern, inside the function.
The static keyword (static and extern are mutually exclusive), applied to the definition of an external variable, changes this a bit: the variable can only be accessed by the functions in the same module where it was defined. But it is possible for a function in the same module to pass a reference (pointer) of the variable to another function in another module. In this case, even though the function is in another module, it can read and modify the contents of the variable—it just cannot refer to it by name.
It is also possible to use the static keyword on the definition of a local variable. Without the static keyword, the variable is automatically allocated when the function is called and released when the function exits (thus the name "automatic variable"). Its value is not retained between function calls. With the static keyword, the variable is allocated when the program starts and released when the program ends. Its value is not lost between function calls. The variable is still local, since it can only be accessed by name inside the function that defined it. But a reference (pointer) to it can be passed to another function, allowing it to read and modify the contents of the variable (again without referring to it by name).
External variables are allocated and initialized when the program starts, and the memory is only released when the program ends. Their lifetime is the same as the program's.
If the initialization is not done explicitly, external (static or not) and local static variables are initialized to zero. Local automatic variables are uninitialized, i.e. contain "trash" values.
The static keyword applied to a function definition prevents the function from being called by name from outside its module (it remains possible to pass a function pointer out of the module and use that to invoke the function).
Example (C programming language)
File 1:
int GlobalVariable; // implicit definition
void SomeFunction(); // function prototype (declaration)
int main() {
GlobalVariable = 1;
SomeFunction();
return 0;
}
File 2:
extern int GlobalVariable; // explicit declaration
void SomeFunction() { // function header (definition)
++GlobalVariable;
}
In this example, the variable GlobalVariable is defined in File 1. In order to utilize the same variable in File 2, it must be declared. Regardless of the number of files, a global variable is only defined once, however, it must be declared in any file outside of the one containing the definition.
If the program is in several source files, and a variable is defined in file1 and used in file2 and file3, then extern declarations are needed in file2 and file3 to connect the occurrences of the variable. The usual practice is to collect extern declarations of variables and functions in a separate file, historically called a header, that is included by #include at the front of each source file. The suffix .h is conventional for header names.
Extern defines a variable or a function that can be used from other files... I highly advise reading some of the many articles available on the Internet on C programming: https://www.google.ca/search?client=opera&rls=en&q=learn+c&sourceid=opera&ie=utf-8&oe=utf-8&channel=suggest
extern char **environ;
the variable environ comes from your library which you will link.
That variable saved the system environment variables of your current
linux system. That's why you can do so.

Strange error while executing a C code in MSVC 2005

I am facing following quirky error.
I have a workspace in MSVS2005 of all C code. I have declared a global variable in one C file.(file1.c) This file has function main() in which, I initilaize the value of that variable = 0.In other C file(file2.c). From main there is a function call to a function(func1 in file2.c) which sets the value of this global variable to 1. In file2.c I have declared the global variable as "extern .." and accessed it. But what i noticed is that in the main function moment the code execution enter the function func2, I see in the watch window that the address of that global variable itself is changed to a totally different address(In watch window I am watching &variable). As a result, when the value of that variable is set to 1, it writes the value 1 to altogether different memory address itself. So when later I use this variable to check in a if condition(if variable == 1), it still shows value of 0 and does not go satisfy the if condition and does not take that code path , where it was expected to have taken that path.
Workaround:
I declared that variable in one of my exisitng global structure, and then accessed this variable for doing the same operations; the code works as expected.
So what could be the explanation for the error which is causing the address of the global variable to be changed if its declared as a global in some C file? It does not matter in which *.c file i declare it and which file I access it using "extern" , the result is same global variable address change and subsequent errorneous operation.No optimization option is enabled.
Thanks,
-AD
Can only guess without actually seeing the code, but here are 2 possibilities:
the global variable is being hidden by a local in either main() or func2() (or maybe func1() - the question mentions func1() but I suspect that's a typo - this is why cutting and pasting code is quite important);
you are mistakenly declaring the global variable as static in file1.c and have an initializer on your extern declaration in file2.c. Having an initializer on the extern declaration will cause that declaration to be a definition, too.
Maybe try declaring it volatile (not sure if that's even valid for globals) and disable any compiler optimizations in case it's getting tricky somehow.
If the variable has a different address in different translation units, you are not seeing one but at least two variables with the same name.
Most common cause: You may have accidently declared a local variable on the stack with the same name. Check your code for this. If the variables are really global the linker should complain if two translation units contain the same symbol.
If this does not help, and if you still see multiple copies of the same symbol-name it's probably best to take a look at the map file (can be enabled in the linker-settings).
All external symbols are listed there with their name, address and (most important in your case) the object-file that contained them.
The addresses in the map-file may be just offsets. In this case do all your calculations relative to a symbol that is known to exist only once. the main() entrypoint might be good for this.
Probably a typo or some thing similar in your code. Try this working demo:
file1.c
int variable;
void fun1(int k);
int main()
{
printf("%d\n", variable);
fun1(4);
printf("%d\n", variable);
}
file2.c
extern int variable;
void fun1(int k)
{
variable = k;
}
Output:
0
4
To compile:
cl.exe file1.c file2.c

Resources