Does char* cause memory leak if passed to a function - c

I have a function like this:
void readString(char* str){
str="asd";
}
Can I know if str will be dealloced? Or must I free it?
Note: I can't use string library as I am programming a microprocessor.

free() must only be called if malloc(), calloc() or realloc() was used to allocate memory. This is not the case in the posted code so calling free() is unrequired.
The "asd" is a string literal and exists for the lifetime of the program (has static storage duration).

Your function does nothing.
It doesn't "read" a string. All it does it assign the address of a string literal (a constant block of memory somewhere that is initialized to the text of the string) to the function's local variable str. The function then exits, causing that local variable to stop existing.
Nothing is returned, and the pointer is not de-referenced (which would in turn be wrong since it's only a char *, not a char * *), so nothing happens outside the function. The caller doesn't "get" any value, and thus has nothing to call free() on, so that problem can never even occur.

String will not be deallocated because it is stored in static memory. You didn't allocate it, you don't free it

No, there is no memory leak. In your case it is statically allocated.

In general you have to make up your own rules about who can or must free memory, and you should document your code so it is clear what the requirements are.
In the example given, readString() only overwrites its own private copy of the pointer, and when it returns the caller will not see that anything has changed. Consequently the caller will have the same duty to free() its pointer as it had before it called readString(), and there will be no leak.
However, if readString() instead accepted a char **, so that it could modify the caller's copy of the pointer, then the outcome would be that it would not be legal to call free() after calling readString(), as the pointer's new value is not part of the malloc heap.
If the previous value of that pointer variable had been a malloc()ed object, then the caller should have freed it before allowing the pointer to be overwritten. It would be truly horrible to have readString() call free() in that case, because it would turn a variable which must eventually be freed into one which must never be freed, and the program flow would be very hard to follow.

This code is useless and meaningless as for as I am concerned. Here are different ways of calling your function definition and why I say this!
int main (int argc, char *argv[], char *envp[])
{
char a, *b, *c;
b = malloc (10);
readString(&a); // Case-1, Valid calling.
readString(b); // Case-2, Valid calling.
readString(c); // Case-3, Invalid calling. Unallocated location.
}
Case-1: This is the only case, where it matters to the caller about what you do in your function. You may use the passed character as you wish. The only meaningful assignment would be something like this. Doing 'str = "asd";' would probably dump the core or mess with the caller's stack or data segment memory(if address of a global variable was passed) and create a complicated debugging nightmare!
void readString(char* str){
*str='a';
}
Case-2: There is nothing Fatal or Syntax error in the code, but it is meaningless to do this. The only meaningful thing would be, just using what ever passed to your function from the caller. What is the reason for assigning like this on the passed parameter? Your definition can just have a local variable and avoid parameter passing completely. That function can be called as "readString();"...
void readString(void){
char *str='asd';
}

Related

Is memory allocated with malloc or calloc deallocated at the end of a function?

I pass a pointer of a given type to a function.
In the function I allocate the memory needed:
Pointer = (mytype * ) malloc (N* sizeof (mytype));
And it all goes well. After the function ends another one calls pointer.
But the previously filled pointer is now without memory.
Shouldn't pointer have kept its filled memory?
Or does the ending of a function deallocate the memory?
Sorry but I am unable to paste my code because I work on a non connected PC.
No. Memory allocated by malloc is not deallocated at the end of a function.
Otherwise, that would be a disaster, because you would be unable to write a function that creates a data structure by allocating memory for it, filling it with data, and returning it to the caller.
No, but you're not returning the pointer to the caller. The argument inside the function is not the same as the value at the calling site, so changing it by assigning the return value from malloc() doesn't change the caller's value.
This:
Foo *foo;
AllocateAFoo(foo);
has no chance of changing the value of foo after the function returns, even if the argument is assigned to inside the function. This is why malloc() returns the new value.
You need to do that also:
mytype * Allocate(size_t num)
{
return malloc(num * sizeof (mytype));
}
This means that there's no point in sending the uninitialized pointer from the caller to the function, so don't.
Also, you shouldn't cast the return value of malloc() in C.
Also, you need to be aware that malloc() is just a function like any other. How would you write a function that reacts when execution leaves other functions? The answer is of course "you can't", and thus malloc() can't either.
You can use alloca(), but that's not supported on all architectures.

Returning pointer freed inside function

This doesn't seem to have any problems running but I'm thinking when it returns, buff might automagically be freed which would in turn free *string and cause problems the next time I allocate and that memory gets overwritten (or worse, etc etc). I don't want to test by trial and error because I may simply have been lucky in my tests so far. Am I doing this wrong?
void strCat1000(char *concatDest, char *format, ...)
{
char buff[1000];
va_list arg_ptr;
va_start(arg_ptr, format);
vsnprintf(buff, sizeof(buff), format, arg_ptr);
va_end(arg_ptr);
free(concatDest);
concatDest=buff;
}
More concisely, is concatDest pointing to freed memory after this function returns?
concatDest=buff;
}
This last statement will not change the observable behavior of the program and is very likely to be just optimized out by any decent compiler.
Remember C passes arguments by value and you are not modifying the original pointer but a local copy in your function.
concatDest=buff;
Not a good idea because when the function returns, all its local variables are destroyed. So if you try to access data (outside this function) that was stored in buff whose address was assigned to concatDest, you will Segmentationf fault
You should be,
taking a length parameter
passing concatDest to vsnprintf
..but then you're just left with snprintf
buff is allocated on the stack, and assigning concatDest to its address won't work since the memory it points to goes away as soon as the stack is popped (when you return).
More concisely: Yes, the memory has been freed. It may not have been overwritten (so it might appear to work for a little bit) but it will be very soon.
buff is a local variable, so it is invalid (popped off the stack) when the function returns. But then so is concatDest, so there's no problem -- you just have a local variable that points at a local variable and both go away at the same time.
Now what you might be thinking of is if you call this function like:
strCat1000(string, "some format", some other args);
but in this case, string is not affected by changes to concatDest in the function -- arguments are passed by value in C. Of course, this means that your function has no effect
at all -- it prints into a temp buffer and then destroys that buffer, but it has no effect on
string or *string in the process.

Why is it bad to return an auto (internal scope) pointer? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
returning a local variable from function in C
The more I think about this, the less I am sure why this is not such a good idea... The compiler complains about having an auto variable from inside the function return to the caller. For instance:
char * foo() {
char bar[11];
fgets(bar, 10, stdin);
return bar;
}
Versus:
char bar[11];
char * foo() {
fgets(bar, 10, stdin);
return bar;
}
I am probably not making much sense. I don't quite understand the problem of having a pointer declaration inside, would the the caller simply not just assume the memory address?
In your first example, the array bar is local to the function, so that it doesn't exist any more when the function returns. Hence the resulting pointer isn't likely to point at anything useful, because what it used to point at doesn't exist anymore.
bar, for all intents and purposes, ceases to exist when your function returns. It is allocated with automatic storage duration and attempts to read from that memory later result in undefined behavior. Since a stack is typically used, how would you imagine keeping that data around in a valid state once the function has returned?
Instead, you can take a char* as input to the function, along with the size of the memory block it refers to, and fill that buffer for the caller, i.e.,:
void foo(char *buf, buf_size) {
fgets(buf, buf_size, stdin);
}
This is very common and idiomatic in C. Look at what fgets is doing. It is asking you, the caller, to supply a buffer to fill. This avoids confusion on who is responsible for deallocating the memory returned from a function (which you would have to document if your function returned a pointer to dynamically allocated memory).
BTW, fgets reads num-1 characters and null terminates for you, so just pass the size of the buffer, no need to pass size-1 as you are currently doing.
The first example is completely wrong. You create memory space and write there inside function and return pointer to it, so you're returning pointer to a non-existent memory segment. This memory will be freed after returning from function. Second example is correct, but you should avoid using global variables if possible.
Edit: If you want memory to be usable outside the function after returning pointer to it, use dynamic memory allocation (check calloc function).

Freeing pointers from inside other functions in C

Consider the c code:
void mycode() {
MyType* p = malloc(sizeof(MyType));
/* set the values for p and do some stuff with it */
cleanup(p);
}
void cleanup(MyType* pointer) {
free(pointer);
pointer = NULL;
}
Am I wrong in thinking that after cleanup(p); is called, the contents of p should now be NULL? Will cleanup(MyType* pointer) properly free the memory allocation?
I am coding my college assignment and finding that the debugger is still showing the pointer to have a memory address instead of 0x0 (or NULL) as I expect.
I am finding the memory management in C to be very complicated (I hope that's not just me). can any shed some light onto what's happening?
Yes that will free the memory correctly.
pointer inside the cleanup function is a local variable; a copy of the value passed in stored locally for just that function.
This might add to your confusion, but you can adjust the value of the variable p (which is local to the mycode method) from inside the cleanup method like so:
void cleanup(MyType** pointer) {
free(*pointer);
*pointer = NULL;
}
In this case, pointer stores the address of the pointer. By dereferencing that, you can change the value stored at that address. And you would call the cleanup method like so:
cleanup(&p);
(That is, you want to pass the address of the pointer, not a copy of its value.)
I will note that it is usually good practice to deal with allocation and deallocation on the same logical 'level' of the software - i.e. don't make it the callers responsibility to allocate memory and then free it inside functions. Keep it consistent and on the same level.
cleanup will properly free p, but it won't change its value. C is a pass-by-value language, so you can't change the caller's variable from the called function. If you want to set p from cleanup, you'll need to do something like:
void cleanup(MyType **pointer) {
free(*pointer);
*pointer = NULL;
}
And call it like:
cleanup(&p);
Your code is a little bit un-idiomatic, can you explain a bit better why you want to write this cleanup function?
Yes
Yes
Yes: There is a block of memory magically produced by malloc(3). You have assigned the address of this memory, but not the memory itself in any meaningful way, to the pointer p which is an auto variable in mycode().
Then, you pass p to cleanup(), by value, which will copy the pointer and, using the copy local to cleanup(), free the block. cleanup() then sets it's own instance of the pointer to NULL, but this is useless. Once the function is complete the parameter pointer ceases to exist.
Back in mycode(), you still have pointer p holding an address, but the block is now on the free list and not terribly useful for storage until allocated again.
You may notice that you can even still store to and read back from *p, but various amounts of downstream lossage will occur, as this block of memory now belongs to the library and you may corrupt its data structures or the data of a future owner of a malloc() block.
Carefully reading about C can give you an abstract idea of variable lifetime, but it's far easier to visualize the near-universal (for compiled languages, anyway) implementation of parameter passing and local variable allocation as stack operations. It helps to take an assembly course before the C course.
This won't work as the pointer in cleanup() is local, and thus assigning it NULL is not seen by the calling function. There are two common ways of solving this.
Instead of sending cleanup the pointer, send it a pointer to the pointer. Thus change cleanup() as follows:
void cleanup(MyType** pointer)
{
free(*pointer);
*pointer = NULL;
}
and then just call cleanup(&p).
A second option which is quite common is to use a #define macro that frees the memory and cleans the pointer.
If you are using C++ then there is a third way by defining cleanup() as:
void cleanup(MyType& *pointer)
{
// your old code stays the same
}
There are two questions are here:
Am I wrong in thinking that after
cleanup(p); is called, the contents of
p should now be NULL?
Yes, this is wrong. After calling free the memory pointed by the pointer is deallocated. That doesn't mean that the content pointed by the pointer is set to NULL. Also, if you are expecting the pointer p to become NULL in mycode it doesn't happen because you are passing copy of p to cleanup. If you want p to be NULL in mycode, then you need a pointer to pointer in cleanup, i.e. the cleanup signature would be cleanup(MyType**).
Second question:
Will cleanup(MyType* pointer) properly
free the memory allocation?
Yes, since you are doing free on a pointer returned by malloc the memory will be freed.
It's not just you.
cleanup() will properly clean up your allocation, but will not set the pointer to NULL (which should IMHO be regarded as separate from cleanup.) The data the pointer points to is passed to cleanup() by pointer, and is free()ed properly, but the pointer itself is passed by value, so when you set it to NULL you're only affecting the cleanup() function's local copy of the pointer, not the original pointer.
There are three ways around this:
Use a pointer to a pointer.
void cleanup(struct MyType **p) { free(*p); *p = NULL; }
Use a macro.
#define cleanup(p) do { free(p); p = NULL; } while(0)
or (probably better):
void cleanup_func(struct MyType *p) { /* more complicated cleanup */ }
#define cleanup(p) do { cleanup_func(p); p = NULL; } while(0)
Leave the responsibility of setting pointers to NULL to the caller. This can avoid unnecessary assignments and code clutter or breakage.

Returning a pointer to an automatic variable

Say you have the following function:
char *getp()
{
char s[] = "hello";
return s;
}
Since the function is returning a pointer to a local variable in the function to be used outside, will it cause a memory leak?
P.S. I am still learning C so my question may be a bit naive...
[Update]
So, if say you want to return a new char[] array (ie maybe for a substring function), what do you return exactly? Should it be pointer to an external variable ? ie a char[] that is not local to the function?
It won't cause a memory leak. It'll cause a dangling reference. The local variable is allocated on the stack and will be freed as soon as it goes out of scope. As a result, when the function ends, the pointer you are returning no longer points to a memory you own. This is not a memory leak (memory leak is when you allocate some memory and don't free it).
[Update]:
To be able to return an array allocated in a function, you should allocate it outside stack (e.g. in the heap) like:
char *test() {
char* arr = malloc(100);
arr[0] = 'M';
return arr;
}
Now, if you don't free the memory in the calling function after you finished using it, you'll have a memory leak.
No, it wont leak, since its destroyed after getp() ends;
It will result in undefined behaviour, because now you have a pointer to a memory area that no longer holds what you think it does, and that can be reused by anyone.
A memory leak would happen if you stored that array on the heap, without executing a call to free().
char* getp(){
char* p = malloc(N);
//do stuff to p
return p;
}
int main(){
char* p = getp();
//free(p) No leak if this line is uncommented
return 0;
}
Here, p is not destroyed because its not in the stack, but in the heap. However, once the program ends, allocated memory has not been released, causing a memory leak ( even though its done once the process dies).
[UPDATE]
If you want to return a new c-string from a function, you have two options.
Store it in the heap (as the example
above or like this real example that returns a duplicated string);
Pass a buffer parameter
for example:
//doesnt exactly answer your update question, but probably a better idea.
size_t foo (const char* str, size_t strleng, char* newstr);
Here, you'd have to allocate memory somewhere for newstr (could be stack OR heap) before calling foo function. In this particular case, it would return the amount of characters in newstr.
It's not a memory leak because the memory is being release properly.
But it is a bug. You have a pointer to unallocated memory. It is called a dangling reference and is a common source of errors in C. The results are undefined. You wont see any problems until run-time when you try to use that pointer.
Auto variables are destroyed at the end of the function call; you can't return a pointer to them. What you're doing could be described as "returning a pointer to the block of memory that used to hold s, but now is unused (but might still have something in it, at least for now) and that will rapidly be filled with something else entirely."
It will not cause memory leak, but it will cause undefined behavior. This case is particularly dangerous because the pointer will point somewhere in the program's stack, and if you use it, you will be accessing random data. Such pointer, when written through, can also be used to compromise program security and make it execute arbitrary code.
No-one else has yet mentioned another way that you can make this construct valid: tell the compiler that you want the array "s" to have "static storage duration" (this means it lives for the life of the program, like a global variable). You do this with the keyword "static":
char *getp()
{
static char s[] = "hello";
return s;
}
Now, the downside of this is that there is now only one instance of s, shared between every invocation of the getp() function. With the function as you've written it, that won't matter. In more complicated cases, it might not do what you want.
PS: The usual kind of local variables have what's called "automatic storage duration", which means that a new instance of the variable is brought into existence when the function is called, and disappears when the function returns. There's a corresponding keyword "auto", but it's implied anyway if you don't use "static", so you almost never see it in real world code.
I've deleted my earlier answer after putting the code in a debugger and watching the disassembly and the memory window.
The code in the question is invalid and returns a reference to stack memory, which will be overwritten.
This slightly different version, however, returns a reference to fixed memory, and works fine:
char *getp()
{
char* s = "hello";
return s;
}
s is a stack variable - it's automatically de-referenced at the end of the function. However, your pointer won't be valid and will refer to an area of memory that could be overwritten at any point.

Resources