I came across lot of functions returning char pointers in one legacy application. Some of them returning pointers to local character arrays. It seems to be causing crashes a
It is not safe. The reason is simple:
Any variable on a function will be allocated on the stack whose memory is freed after the function returns. The fact that the memory is freed does not mean that its content is changed.
This means that the memory content you did put in the variable char buff[20]
is still at the buff
or ptr
(since ptr=buff
) memory position. Whenever you call another function (or execute another block), its function/block variables will go to the stack too, creating the possibility of changing the memory content for whose the position ptr
points to.
In the strcpy
example you wrote, you were lucky enough that the strcpy function variables did not get on the stack at a position that were inside the old buff
array. This is the reason you got the impression that it was safe.
The conclusion is that there is no way you can really guarantee that a freed memory content of the stack will not change between two function calls.
The solution is to use malloc
because malloc
does not allocate memory on the stack but on the heap. Heap memory is not deallocated unless you chose to do so (by a free call).
This approach would guarantee that the memory pointed by ptr
is safe to be used by any other function.
The drawback of this solution is intrinsic: once the memory is not deallocated unless you programatically do that, if you forget to free this memory and lose the content of ptr
, this memory will be there, allocated for your program but never achievable, lost for as long as your program runs. This memory will become a memory leak :-)
This is one reason why some languages have garbage collectors... but this is another story :-)
PS.: I think that it is safe (if your program is single threaded), although I do not recommend, to do something like that:
{
char safe_buffer[20];
char *unsafe_ptr;
int i;
unsafe_ptr = f1();
/*Copy the buffer without calling any function
not to change the stack content
*/
for(i=0;i<20 && *(unsafe_ptr + i) != 0;i++)
{
*(safe_buffer + i) = *(unsafe_ptr + i);
}
*(safe_buffer + i) = 0;
f2(safe_buffer);
}
No, you see buff[20]
is only available inside the f1
function. To be precise, the memory is allocated on f1
s stack.
You need to create a new buff[20]
on the heap using malloc
and return a pointer to that memory from inside f1
. Another way is to create buff[20]
outside f1 (from the function which calls f1
) and send it as an argument to f1
. f1
can then change the contents of the buffer and doesn't even have to return it.
Actually, the best would be to modify f1() to use malloc(). Your solution isn't near defined behavior.
Is the following usage safe?
No.
If your function returns a pointer to anything, make sure it allocates a memory area and returns the pointer to it:
char *safe_f1(void) {
char *ptr;
ptr = (char *) malloc(20 * sizeof(char));
...
return ptr;
}
the malloc solutions are interesting except that the memory should be free after usage. (outside the function). Else there would be a memory leak.
Never return a pointer to local variable. It may work in some situations, but in general you will have lots of problems with it. Instead: