In c, let us say I have the following code:
int func(){
char* s = "bla";
}
I am not sure as to what this is compiled.
Since s isn't static, it doesn't survive after func() ends so it seems that the pointer to "bla" is lost.
On the other hand, the program should still know the address to "bla" so the next time func() is called, s will get the same address.
I wonder if the above code is ok or if I must declare s as static?
It is not clear how you are going to use this local pointer. Nevertheless the address of the string literal will be the same. It does not depend on how many times the function will be called. This string literal has static storage duration. So the pointer will be initialized with the same address each time when the function gets the control. There is no need to declare the pointer itself as static unless you change its initial value and want that it would be stored in the pointer between function's calls.
Related
For one of my projects, I am using a pointer to point a float type global variable. I am wondering if I define this as static vs local pointer with in a function, would one be a better definition than the other.
For Ex:
float a;
float b;
void foo(void)
{
static float *ptra;
float *ptrb;
ptra = &a;
ptrb = &b;
}
A static pointer is used to implement a function which returns the same buffer to the program, allocating it the first time it is called
Apart from
ptrb = &b;
being pointless (scope etc...)
Why use static pointer?
It serves no purpose and is very bad coding style.
If using a non static definition covers all needs, then use this. If it doesn't, use static.
I think the other answer is correct. I would add this as explanation: A static pointer (or variable) has the same life cycle than a global pointer (or variable), except that its "scope" is limited to the function.
It is not only used to return the same buffer (only one use case). You can also use it for other situations. For example if you want to implement a global counter or just save some state during the whole program life cycle (can be useful for a recursive function).
From my personal experience you may use it only in very rare cases.
static is persistent so if you declare it in a function, when you call the function again the value is the same as it was last time.
So use them when you need same value whenever function is called.
And about local pointer if pointer points to a local variable in the function block , so outside function block scope of variable ends and the pointer becomes dangling pointer . And thus accessing such pointer will cause segmentation fault.
For example:
void func1(){
int i = 123;
func2(&i);
}
void func2(int *a){
*a = 456;
}
When func1 calling func2, a pointer to local variable is passed to func2 -- the pointer is pointed to the stack. Is this safe for the rules of C?
Thanks.
The scope of i is func1 and it outlives the call to func2. So it is perfectly safe.
As stated in most of the answers before, it is perfectly safe to pass the pointer to func2() in your special case.
In a real world piece of software however, I consider this harmful as you don't have control on what func2() is doing with your variable. func2() may create an alias to its parameter to use it asynchronously at a later point in time. And at that time, the local variable int i may be gone when this alias is used later.
So from my point of view passing a pointer to a local (automatic) variable is extremely dangerous and should be avoided.
You may do so if you declare the variable in func1() as static int i;
In that case, it is ensured, that the memory for i won't get recycled and overwritten. However you will need to setup some Mutex locking for access control to this memory in a concurrent environment.
To illustrate this problem here is some code I just stumbled in yesterday while doing software testing at my customer. And yes, it crashes...
void func1()
{
// Data structure for NVMemory calls
valueObj_t NVMemObj;
// a data buffer for eeprom write
UINT8 DataBuff[25];
// [..]
/* Assign the data pointer to NV Memory object */
NVMemObj.record = &DataBuff[0];
// [..]
// Write parameter to EEPROM.
(void)SetObject_ASync(para1, para2, para3, &NVMemObj);
return;
}
void SetObject_ASync(para1, para2, para3, valueObj_t *MemoryRef)
{
//[..]
ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr = MemoryRef->record;
//[..]
return;
}
In this case, the data in the DataBuff is long gone when the pointer in ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr is used to store the data to the EEPROM.
To fix this code, it is at least necessary to declare static UINT8 DataBuff[25]; Additionally, it shall be considered to also declare static valueObj_t NVMemObjas we don't know what the called function is doing with that pointer.
To put it briefly:
TL;DR
Even though it is legal in the C-language I consider it as harmful to pass pointers to automatic variables in a function call. You never know (and often you don't want to know) what exactly the called function does with the passed values. When the called function establishes an alias, you get in big trouble.
Just my 2 cents.
Yes it is safe to pass a pointer to a local variable but you can't return a pointer to an automatic local variable from a function.
Yes, your code is safe.
As long as the object's lifetime is not over, it's safe to pass local variables like you do.
Is this safe for the rules of C?
What you are doing is safe as the local variable is still valid and within the scope. Accessing the local varaible outside of its scope is undefined behvaior but this is totally fine
In your case, you can safely use &i till the time i is valid.
Now, as we can see i has a lifetime till the end of func1(). As, the func2() is being called from the func1() and the func1() has not yet finished execution, so, i is still valid.
That's why , usually passing the address of a local variable to another function is usually allowed (the variable's lifetime is not over) but, returning the address of a local variable (immediately after return, local variables of the function cease to exist) is not allowed.
TL;DR :You can safely use &i as the argument of func2() as shown here.
This question already has answers here:
Is returning a pointer to a static local variable safe?
(7 answers)
Closed 8 years ago.
Here is the code,
char *foo()
{
static char s[10] = "abcde";
return s;
}
char *bar()
{
char *c = foo();
return c;
}
int main()
{
printf("%s\n", bar());
}
Typically, it is wrong to return a local pointer as I did in bar, but now c points to a static var returned by foo, would it be correct to return a local var c in bar?
I tried, it printf the right value, but I don't understand how it works. I thought, when bar() finishes, the var c should vanish, which should make printf print undefined stuff, right?
Follow Up
char *c is a local var, if char *c = "abcde";, I assume this: c is a local var which resides in the function's stack, while "abcde" is a constant var which resides in the constants-area (part of the heap?), so when bar() finishes, c vanishes, but "abcde" still remains in the heap, right?
Variable c is only a pointer. It is not wrong to return a local pointer from a function, you do it all the time. For example, when you store a result of malloc in a pointer, the pointer is local, but the storage it points to is not. It is, however, wrong to return a pointer to a local storage. Since in your example c never points to a locally allocated data, your code works correctly as written.
EDIT (in response to the Follow Up)
"abcde" is a constant var which resides in the constants-area (part of the heap?)
The constants area is not usually part of the heap, it is either a separate arrea, usually adjacent to the area where the machine code of your program is stored.
c vanishes, but "abcde" still remains in the heap, right?
"abcde" remains in the constants area, not in the heap, but the concept is correct: the pointer to that constant remains valid throughout the entire run-time of your program.
The value of c is returned, which is foo() which is s which is the address of "abcde". What vanish after bar returns is the space in which that value was stored when you did char *c = foo();.
So, yes, it's correct.
Your intuition is correct, but the issue you seem to be having is this:
There are three types of storage in C,
Automatic (the normal local storage) Which lives on the stack and pointers to this data are no longer valid after the return of the function.
Dynamic (think malloc) Which lives in the heap and pointers to this data are no longer valid after free() is called.
Static Which lives in the data segment (and so it doesn't disappear).
Since s is a static variable it lasts for the entire lifetime of the program. And so, no it will not vanish when foo returns.
Edit: I should add that there is also register, but that is largely ignored by most compilers.
static local variable inside a function will stay in memory till the application ends, and does not go away when the function returns. That is why having a pointer to the static variable gives you valid data in printf even outside of the function foo.
If the local variable is not static, the same test would fail as the variable goes away as the function returns.
I recently read about scope rules in C. It says that a local or auto variable is available only inside the block of the function in which it is declared. Once outside the function it no longer is visible. Also that its lifetime is only till the end of the final closing braces of the function body.
Now here is the problem. What happens when the address of a local variable is returned from the function to the calling function ?
For example :-
main()
{
int *p=fun();
}
int * fun()
{
int localvar=0;
return (&localvar);
}
once the control returns back from the function fun, the variable localvar is no longer alive. So how will main be able to access the contents at this address ?
The address can be returned, but the value stored at the address cannot reliably be read. Indeed, it is not even clear that you can safely assign it, though the chances are that on most machines there wouldn't be a problem with that.
You can often read the address, but the behaviour is undefined (read 'bad: to be avoided at all costs!'). In particular, the address may be used for other variables in other functions, so if you access it after calling other functions, you are definitely unlikely to see the last value stored in the variable by the function that returned the pointer to it.
Why then is a function returning a pointer ever required?
One reason is often 'dynamic memory'. The malloc() family of functions return a pointer to new (non-stack) memory.
Another reason is 'found something at this location in a value passed to me'. Consider strchr() or strstr().
Another reason is 'returning pointer to a static object, either hidden in the function or in the file containing the source for the function'. Consider asctime() et al (and worry about thread-safety).
There are probably a few others, but those are probably the most common.
Note that none of these return a pointer to a local (stack-based) variable.
The variable is gone, but the memory location still exists and might even still contain the value you set. It will however probably get overwritten pretty fast as more functions are called and the memory address gets reused for another function's local variables. You can learn more by reading about the Call Stack, which is where local variables of functions are stored.
Referencing that location in memory after the function has returned is dangerous. Of course the location still exists (and it may still contain your value), but you no longer have any claim to that memory region and it will likely be overwritten with new data as the program continues and new local variables are allocated on the stack.
gcc gives me the following warning:
t.c: In function ‘test’:
t.c:3:2: warning: function returns address of local variable [enabled by default]
Consider this test program:
int * test(int p) {
int loc = p;
return &loc;
}
int main(void) {
int *c = test(4);
test(5);
printf("%d\n", *c);
return 0;
}
What do you think this prints?
void someFunc()
{
int stackInt = 4;
someOtherFunc(&stackInt);
}
Is it the case that stackInt's address space could be reallocated after someFunc ends, making it unsafe to assume that the value passed to someOtherFunc represents the stackInt variable with value 4 that was passed to it? In other words, should I avoid passing stack variables around by address and expecting them to still be alive after the function they were initialised in has ended?
Yes, definitely.
You don't have to avoid passing stack-allocated variables by reference/pointer altogether, though, just storing pointers or references to stack-allocated variables.
After someFunc() returns and another function is called, the space that was used for stackInt will be used for some other variable in the new function. Therefore, the function someOtherFunc() cannot safely assume that if it keeps a copy of the pointer it is passed, that pointer will remain valid. If it stashes a copy of the value that was pointed at, that is fine.
So, although it is fine to pass stack variables around by address (so, for example someOtherFunc() could modify the value of stackInt and, if there was code in someFunc() that accessed it after the call, the value might not be 4 still), it is not safe to store the pointer and expect it to point to anywhere valid after someFunc() returns.
It is absolutely fine to pass stack variables as parameters in all possible ways
The stack allocated variables will be overwritten only when the function declaring those variables is completed its execution.
So until you return from someFunc() there is no harm to stackInt.
As long as you don't spawn new thread from someOtherFunc and use stackInt there, this will work.