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.
Related
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';
}
It is known that if we pass a pointer by value to a function, it cannot be freed inside the function, like so:
void func(int *p)
{
free(p);
p = NULL;
}
p holds a copy of a (presumably valid) address, so free(p) tries to, well, free it. But since it is a copy, it cannot really free it. How does the call to free() know that it cannot really free it ?
The code above does not produce an error. Does that mean free() just fails silently, "somehow" knowing that address passed in as argument cannot be worked upon ?
p holds a copy of a (presumably valid) address, so free(p) tries to, well, free it. But since it is a copy, it cannot really free it.
It's not true. free() can work just fine if p is a valid address returned by malloc() (or NULL).
In fact, this is a common pattern for implementing custom "destructor" functions (when writing OO-style code in C).
What you probably mean is that p won't change to NULL after this - but that's natural, since you're passing it by value. If you want to free() and null out the pointer, then pass it by pointer ("byref"):
void func(int **p)
{
if (p != NULL) {
free(*p);
*p = NULL;
}
}
and use this like
int *p = someConstructor();
func(&p);
// here 'p' will actually be NULL
The only problem is if this function is in a different DLL (Windows). Then, it may be linked with a different version of the standard library and have different ideas on how the heap is built.
Otherwise no problem.
Passing p to func() by value, which will copy the pointer and creates the local copy to func() which frees the memory. func() then sets it's own instance of the pointer p to NULL but which is useless. Once the function is complete the parameter p come to end of existence. In calling function you still have pointer p holding an address, but the block is now on the free list and not useful for storage until allocated again.
What everybody is saying is that your memory will be freed by free(p);, but your original pointer (which you use to call the function with) will still hold the (now invalid) address. If a new block of memory including your address is allocated at a later stage than your original pointer will become valid (for memory manager) again, but will now point to completely different data causing all sorts of problems and confusion.
No you really free the block of memory. After the function call, the pointer passed to this function is pointing to nowhere : same address but the MMU don't know anymore what to do with this address
Something's wrong with the following function:
typedef struct Data1{
float result;
struct Data1* next;
} Data;
Data* f(Data* info){
Data item;
item.result=info->result;
item.next=info->next;
return &item;
}
I notice two things here:
The returned value is a pointer of local value. However it's still a pointer- the compiler gives a warning: function returns address of local variable. but would it really be a problem? ( I don't return a local value itself)
I believe that the main problem here is that this function suppose to copy the Data struct. it would be OK for the results value, but regarding the 'next' pointers, I believe that at the end of the call to the function the pointers would not be changed, Am I correct? It's like equalize two ints in a outside function, should *(item.next)=*(info->next); solve the problem?
So what's the main problem here? is it both 1 and 2?
The returned value is a pointer of local value. However it's still a pointer- the compiler gives a warning: function returns address of local variable. but would it really be a problem? ( I don't return a local value itself)
That is the main problem. After the function returns, the local variable doesn't exist anymore. The space it occupied may be overwritten immediately or later, but you can't count on ever reading meaningful data from that address.
If you want to copy things, you have to return a pointer to malloced memory.
Data* f(Data* info){
Data *item = malloc(sizeof *item);
item->result=info->result;
item->next=info->next;
return item;
}
But that has the drawback that now the caller has to free the memory allocated by f, so
Data* f(Data* info, Data* item){
item->result=info->result;
item->next=info->next;
return item;
}
with a pointer allocated by the caller.
The problem with returning pointers to local variables is that the space the local variables occupies will be reclaimed when the function returns, so the pointer no longer points to valid memory, or even memory used by other functions called later.
Yes, it would be a problem, since the returned pointer is useless: it's pointing at an object which no longer exists. Hence the warning.
Not sure I follow your reasoning here ... You are not changing anything in the Data passed in, so that's a problem if you expected it to.
1) Yes, it's a problem, because your pointer now points to what used to be on your stack, but is no longer managed memory, which means another function call (or an interrupt) will, with almost 100% certainty, begin mangling that memory.
2) I have no idea what you're asking here.
The main problem is that you're unclear on how memory works in C programs, which leads to constructs like this; not a ding, just an honest observation: http://www.geeksforgeeks.org/archives/14268 gives a relatively good overview and should serve you well.
In following code, is it possible cause some memory leaks?
reference-ril.c
static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
{
....
ATResponse *p_response = NULL;
....
err = at_send_command(cmd, &p_response); // it's a memory leakage or not ?
....
at_response_free(p_response);
....
}
And in other function:
static void requestOrSendPDPContextList(RIL_Token *t)
{
ATResponse *p_response;
....
err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
// it's a leakage or not ?
....
at_response_free(p_response);
....
}
Actually, these function will returned before calling at_response_free(p_response) in some cases.
I suppose we shout set ATResponse *p_response to NULL first, right ?
Set pointer to NULL is a good idea or not?
It depends:
if at_send_command_multiline and at_send_command look at the value pointed-to by their respective last arguments (&p_response), then you should set them to predictable values. This may mean that you set p_response to NULL. If the functions allocate memory for the pointer without looking at the initial value, then you are okay. To answer your particular question, a variable declared in a function, unless declared static, has no default value.
if the at_send_command* functions always allocate memory for the last argument, then you must free the memory. If they allocate only in the case of success, then you must free only in the case of success. A simple rule is that for every malloc() or calloc(), there should be a free(). (realloc() changes this a bit, but you shouldn't need to worry about it right now).
In other words, you need to look at the documentation of at_send_command* functions, or look in the definition of the functions to answer your questions fully.
Setting the pointer to null is certainly a good idea; but neither case is a memory leak.
The initial value of a pointer in C is garbage, as is the initial value of any variable that isn't initialized. (This is because of efficiency, or so I'm told, and needs to be kept in mind.)
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.