Is this use of C pointers safe from leaking memory? - c

char *a() {
char *t = malloc(8);
t[0] = 'a';
t[1] = 'b';
//...
t[7] = 'h';
return t;
}
int main(void) {
char *x = a();
//do something with x
//...
free(x);
return 0;
}
Does this code have any potential problems since memory is allocated in a() and used memory in main()?

First, a() is declared as returning void, but you attempt to return a char*. Change the signature to return a char*.
Second, your function is fine, but your example code has a memory leak because you never free the memory that the returned pointer points to.
Third, as gbrandt pointed out, you are not checking for success after the call to malloc. malloc can fail, and checking to see if it did is a good habit to get into.
Another way to accomplish this would be to pass a pointer to a pointer into a() instead, and then the caller has to create the pointer themselves before passing it to a(), but either way you still need to free the memory. To be honest, I would go with your approach over this in this case. There is no compelling reason to do it this way, just thought I would mention it.
void a(char **p)
{
*p = malloc(8);
if (*p)
{
**p[0] = 'a';
**p[1] = 'b';
...
**p[7] = 'h';
}
}
int main(void)
{
char *x;
a(&x);
//do something with x
.....
free(x);
}
If this alternate approach confuses you, please let me know as I would be happy to provide an explanation (though, at the moment, I need to get back to work!)

All good advice above. Small problems with the code, the big one is...
You are not checking for success in the malloc or after the function call. Never forget error handling.

No problems—in fact, this is the correct way to allocate memory that will still be used after a function returns—but you may want to free() the memory when you're done using it. Eight bytes wouldn't be a problem, but coding against memory leaks is a good habit to get into.

Apart from having the wrong return type on a() (should be char * instead of void), the code doesn't have any problems.
Just be sure to free() the memory you allocated when you're done with it.

Most of the answers here indicate that this isn't a problem, just remember to free() it later. This is technically true, but is really a problem. Any time you allocate memory in one scope and expect it to be freed in another, you are asking for a memory leak. People don't remember to free the memory. There is also the problem that the caller will have to know that you used malloc and not alloca() or new() or something else. If they call anything but the matched deallocation routine, the results are undefined.
In short, it is usually a mistake to allocate memory and pass it back to the caller.
It is better to expect the memory to be allocated by the caller because if they allocate it, they will remember to free it and to do so correctly.

No you won't have any problems explicitly because you allocated the function in a and use it in main.

As long as you remember to free the memory that x points to then you won't have any problems. By using malloc() you've allocated memory on the heap which is left alone when returning to the calling function.

Thanks. I just edited the code. I guess this time it should have no problem. Btw, in C, when a function finishes, does the compiler clear all variables (including array & pointer) in the stack?

Related

Freeing a pointer inside a function, and using it in main

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
char* test() {
char* s = "Hello World";
size_t len = strlen(s);
char* t = malloc(sizeof(char)*(len+1));
strcpy(t, s);
free(t);
return t;
};
int main(void) {
printf("%s\n", test());
return 0;
};
I would like to allocate and de-allocate memory inside the function. I tested this code and works, but I am wondering:
Why does this work?
Is it good practice to use the value of a freed pointer in main ?
Once you call free on a pointer, the memory it pointed to is no longer valid. Attempting to use a pointer to freed memory triggers undefined behavior. In this particular case it happened to work, but there's no guarantee of that.
If the function returns allocated memory, it is the responsibility of the caller to free it:
char* test() {
char* s = "Hello World";
size_t len = strlen(s);
char* t = malloc(sizeof(char)*(len+1));
strcpy(t, s);
return t;
};
int main(void) {
char *t = test();
printf("%s\n", t);
free(t);
return 0;
};
malloc reserves memory for use.
free releases that reservation. In general, it does not make the memory go away, it does not change the contents of that memory, and it does not alter the value of the pointer that held the address.
After free(t), the bytes of t still contain the same bit settings they did before the free. Then return t; returns those bits to the caller.
When main passes those bits to printf, printf uses them as the address to get the characters for %s. Since nothing has changed them, they are printed.
That is why you got the behavior you did with this program. However, none of it is guaranteed. Once free was called with t, the memory reservation was gone. Something else in your program could have used that memory. For example, printf might have allocated a buffer for its own internal use, and that could have used the same memory.
For the most part, malloc and free are just methods of coordinating use of memory, so that different parts of your program do not try to use the same memory at the same time for different purposes. When you only have one part of your program using allocated memory, there are no other parts of your program to interfere with that. So the lack of coordination did not cause your program to fail. If you had multiple routines in your program using allocated memory, then attempting to use memory after it has been released is more likely to encounter problems.
Additionally, once the memory has been freed, the compiler may treat a pointer to it as if it has no fixed value. The return t; statement is not required to return any particular value.
It doesn't matter where do you free() a pointer. Once it is free()d, the pointer is not deferrenciable anymore (neither inside nor ouside the function where it was free()d)
The purpose of free() is to return the memory allocated with malloc() so the semantics are that, once you have freed a chunk of memory, it is not anymore usable.
In C, all parameters are passed by value, so free() cannot change the value expression you passed to it, and this is the reason the pointer is not changed into an invalid pointer value (like NULL) but you are advised that no more uses of the pointer can be done without incurring in Undefined Behaviour.
There could be a solution in the design of free() and it is to pass the pointer variable that holds the pointer by address, and so free() would be able to turn the pointer into a NULL. But this not only takes more work to do, but free() doesn't know how many copies you have made of the value malloc() gave to you... so it is impossible to know how many references you have over there to be nullified. That approach makes it impossible to give free() the responsibility of nullifying the reference to the returned memory.
So, if you think that free doesn't turn the pointer into NULL and for some strange reason you can still use the memory returned, don't do it anymore, because you'll be making mistakes.
You are adviced! :)

Should I use free() in Subfunction after malloc()?

In my project have a sub-function. In this function, I need to store my data temporarily. So I use malloc(), I'm not sure whether is necessary to use free()?
void *hash2(unsigned char *mes, element_t d)
{
size_t iterations = strlen(mes) / 8;
unsigned char *rtemp = malloc(32 * sizeof(char));
SHA256(mes, iterations, rtemp);
element_from_hash(d, rtemp, 32);
free(rtemp);
}
As already stated in the present answer, you should free any memory that is no longer needed, if you allocate memory within the function, not freeing it and not returning any pointer to it will cause a memory leak.
Note that your function *hash2(...), having void* return type, must return a value, if you don't need it to, use void instead.
In your particular code it does seem that you wouldn't need to use malloc anyway, you can use a local array unsigned char rtemp[32];. malloc is a heavy function that involves system calls, if you can avoid it, you should.
Yes, as you are not using the allocated memory anymore, you must free it.
Once you return from the function call, you'll have no way to access the allocated memory, hence it cannot be freed up. So, you need to to pass the pointer to free() before leaving the function scope (as seen in the snippet) to avoid memory leak.

Do I need to/can I free a void pointer in C?

I have a void pointer as a parameter for a function. It is currently pointing to an int. When I try to free it, it returns a bus error. Should I be freeing void pointers? If so, how do I do so?
You have to answer two questions first:
Was it previously allocated with a malloc family function (e.g. calloc)?
Did you inherit ownership of it when making the function call?
If the answer to both of those is "Yes", then it's at your discretion, though presumably you'd do it at the appropriate time and place to avoid "use after free" type bugs.
When you inherit ownership of a pointer you inherit the responsibility for calling free() when you're done using it, or passing on ownership to another part of your code. If you fail in this responsibility you have memory leaks.
As a general rule you should never free() a pointer unless you know with certainty that's what you're supposed to do, and you're allowed to do it.
Some functions return pointers to things that you do not own, and even if you did, they're not valid for free() because they may be offset somehow. Only the original pointer returned from the malloc-type function can be used with free().
For example:
void* getBuffer(size_t size) {
globalBufferOffset += size;
return &globalBuffer[globalBufferOffset];
}
This returns a pointer in the middle of some structure that may or may not be dynamically allocated. You don't own it. You should not call free() on it.
Read the documentation very carefully to understand your responsibilities. You may need to call a special free-type function when you're done with the pointer. You may not. You may need to pay attention to thread safety. There's a lot of things that can be going on here you need to be aware of before making a decision.
If the pointer is allocated by malloc or something like that, you have to free.
Because, the malloc function returns the void * pointer, so YES, you can/need to free this pointer.
There are some cases you should not free, for example, the code below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
void *p1, *p2, *p3;
int x, y;
p1 = &x;
p2 = malloc(sizeof(int));
p3 = malloc(10);
*(int*)p2 = y;
p3 = "abc";
free(p1); // it raises the fault because p1 is not allocated by malloc
free(p2); // it's OK
free(p3); // it raises also the fault because p3 points to string literal
return 0;
}
You need a corresponding delete each new or a free for each malloc.
If you never wrote a new or a malloc you don't need a free.
Some libraries have their own version of new and free. They would also have corresponding methods and hopefully some documentation. Like SDL_CreateRGBSurface and SDL_FreeSurface.

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.

Return an allocated variable

I know we should free any variable allocated with malloc, but what if I return it in a function? Something like this:
char *somefunction(int somearg){
char *str;
str=(char *)malloc(sizeof(char *));
//some code
return str;
}
Should I free str? How could I do that?
You have two options: one, pass a char* to somefunction and use that instead of allocating within somefunction, or two, free the return value later on.
The first option:
char *somefunction(char *str, int somearg){
//some code
return str;
}
// Elsewhere...
char *str = (char *) malloc....;
somefunction(str, 123);
// Code...
free(str);
The second option:
char *somestr = somefunction(123);
// Do something...
free(somestr);
I personally suggest the first option, as it's a little easier to avoid leaking memory when it's not being allocated within arbitary functions.
You free it when you have finished with it. There is no rule that says that the free() that matches a malloc() must be in the same function.
You should free all the allocated space but if you return its because you will use those memory space in other parts of the program, so after you use it you should free. See every place in the code that calls the function and free the space after you use the returned value.
If you intend to return the address of the block you should not free() the block but instead rely on the calling code to free() it later. This is called onwership passing.
If you free it in the function and return the pointer the calling code will run into undefined behavior trying to access the already freed block.
This is a practice for some existing functions (strdup(), for instance) but is generally a bad idea. Requiring that a user be aware of what happens inside a function call is a bad requirement - think how many functions you use who's internals are hidden from you.
Generally speaking, you will want to have a user pass in a buffer and size instead of allocating memory for them.

Resources