Do I understand the memory problems with this malloc/free combo? - c

I have a c function that looks like this
void fn(void *data) {
type *p=malloc(sizeof *p);
p=data;
...
free(p);
}
If I understand correctly, the two problems with this are that the malloc sets aside some memory for p, but the pointer in p is then immediately overwritten by the pointer data so nothing is pointing to the memory allocated to p. Also, the subsequent free actually frees the memory at data so that whatever function called fn will no longer be able to safely access it. Is this right?
What I probably meant to do is:
void fn(void *data) {
type *p;
p=data;
...
}
Since there's no malloc there's nothing to free and the pointer in data continues to point to allocated memory?
EDIT: I should point out that I know for sure that the pointer in data is actually a pointer of the same type as p.
FURTHER EDIT: The pointer in data points to something that was malloc'd elsewhere.

Yes. You understood right. Assigning data to p after allocating memory to p will leave no pointer to the allocated memory by malloc.
A block of memory that's no longer accessible to a program is said to be garbage. A program that leaves garbage behind has a memory leak.
Unfortunately, unlike some other languages, C doesn't have garbage collector.
Another thing is that calling free(p) will invoke undefined behavior because the argument to free must be a pointer that was previously returned by a memory allocation function (or it could be a NULL pointer).

Yes, the function should not free the memory it did not allocate. The principle worth following in most cases is: do not allocate and deallocate in different contexts.

Related

Allocating array on heap in C

I'm allocating an array of of "Todo" structs on the heap like so:
struct Todo *todos = malloc(n * sizeof(*todos));
My understanding is that I have now allocated memory for all of my n Todo structs. So if I want to save some values I can just do for example:
todos[i].id = 1;
The problem now is that if I try to free that memory using free(&todos[i]); I get an error telling me that I haven't allocated that pointer.
My question is now, do I just need to free the todos array and not every element on its own?
You have allocated one single block of memory for all your Todo structures. You can not free a single element. Just like you should not free elements of a non-heap allocated array.
Each call to malloc (or calloc) should be matched by a single call to free.
A little bit of background to Some programmer dude's answer
C11 standard, 7.22.3.3 "The free function", paragraph 2:
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
[emphasis by me]
Background (second level...) is that typically, you did not only receive the memory starting at the pointer, but additionally there is some kind of (machine/OS specific) control block right before the pointer's address that is needed to free the memory again.
You might try to peek at this control block by reading some bytes right before the pointer (just out of curiosity), but be aware that this actually is undefined behaviour as well (so don't ever do this in production code!) and might lead to your programme crashing.
As a reference, always that you do:
WhateverTypeInTheWorld *var1 = malloc(whateveryouwanttocompletearray);
then, you have to do
free(var1); /* use the same value you received from malloc() */
to return the memory back... as you did only one malloc(), you can do only one free() and pass to it the same pointer you got from malloc().
When you write:
free(&todos[i].i);
you are passing free the i-esim element field i's address, and not the pointer you received from malloc(). Probably you understood that you can free part of the memory you received... but it doesn't work that way... you get the memory in chunks, and you have to return it in those same chunks you received from malloc.

Correct usage of free() function in C

I am new in C programming language so can you tell me if this is correct way to do.
for example:
program points on buffer and i use that pointer as parameter in free() function. So, what problems can this function cause ?
You should call free only on pointers which have been assigned memory returned by malloc, calloc, or realloc.
char* ptr = malloc(10);
// use memory pointed by ptr
// e.g., strcpy(ptr,"hello");
free(ptr); // free memory pointed by ptr when you don't need it anymore
Things to keep in mind:
Never free memory twice. This can happen for example if you call free on ptr twice and value of ptr wasn't changed since first call to free. Or you have two (or more) different pointers pointing to same memory: if you call free on one, you are not allowed to call free on other pointers now too.
When you free a pointer you are not even allowed to read its value; e.g., if (ptr) not allowed after freeing unless you initialize ptr to a new value
You should not dereference freed pointer
Passing null pointer to free is fine, no operation is performed.
Think that the computer has a whole bunch of memory not (yet) used by your program. Now you need some more memory and you ask your computer to give you some more (for example, a large buffer). Once you are done with it, you want to return it to the computer.
This memory is called the heap. You ask for memory by calling malloc() and you return it by calling free();
char *buffer;
buffer = malloc(512); // ask for 512 bytes of memory
if (buffer==NULL) return -1; // if no more memory available
...
free(buffer); // return the memory again
free() function is used to deallocate memory used by one program and move it back to available memory area so that other operating system processes can use that memory location. Also free function takes any type of pointer that points to that memory location.
For example:
int a = 10; // suppose 2 byte is allocated ie location 1000 and 1001
Now this 2 byte of memory belongs to specific problem; hence OS will not give this memory location to another process (memory is now allocated memory not available memory)
int *ptr =&a;
/*ptr is pointer variable pointing to 1000
as it is int pointer therefore ptr++ will move pointer to 1002*/
Now if we do free(ptr), it will check the pointer type and depending on type free function deallocate memory in this case 2 bytes starting from 1000.
Now interesting point is your data will be there until OS allocates this memory to some other process and that process overwrites it.
Also ptr is pointing to 1000 even after free() function but that memory location does not belong to our program hence ptr pointer has given new name DANGLING POINTER.
*ptr may or may not give the same value therefore it is better to make ptr =null.
From the man page of free() function:
The free() function frees the memory space pointed to by a pointer ptr which must have been returned by a pre‐
vious call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called
before, undefined behavior occurs. If ptr is NULL, no operation is performed.
You have to use the free() function when you are allocating the memory dynamically.
If you are using that as a static variable then it may lead to unintended behavior.
char *c=malloc(100);//allocating the 100 bytes of memory for a pointer variable c.
Here after usage of that varaible you can free that allocated memory,
free(c);
If you are declared a variable like this,
char c= malloc(100);// It is illegeal. And c will have a memory in stack.
If you free this variable,
free(c);//it will lead to system crash. Because your freeing the memory which is in stack memory.

does free() follow pointers?

I'm sure it doesn't, but maybe there's black magic in it, so here's my question:
If I have a struct like this:
struct mystr {
char * strp,
unsigned int foo,
};
and I allocate memory for it and want to release it later. Do I have to do
free(mystr_var->strp);
free(mystr_var);
or is the last line enought, does the free() function follow the pointers and free them two?
No, free doesn't follow pointers, you need both lines.
I usually write a function like:
void freemystr(mystr *mystr_var)
{
if (mystr_var)
{
free(mystr_var->strp);
mystr_var->strp = NULL;
free(mystr_var);
}
}
Every individually allocated block of memory must be freed individually. free() will only free the memory block that the pointer points to and its has no knowledge of what is the content of that memory.
Hence, in your case you are doing it the right way by first freeing the innermost memory allocated in a structure and finally freeing the struct pointer.
If you just do free on the struct pointer, the struct memory gets freed. The memory held by char* strp, becomes a memory leak in your program lifetime.
No, it doesn't.
It's not magic at all, to the compiler it's just another function call.
Ask youself how you would implement void free(void *); in a way that follows pointers, of course without being fooled by being given a binary data block containing anything. You can't.
No. It simply frees the block pointed to.
You need to explictly free referenced memory. You need to do this first (i.e. most likely in the opposite direction to how you allocated the memory)
No. free won't do recursive free for all members. You have to explicitly free all members for which you have allocated memory.
If you understand how memory is allocated for struct and how free works this won't be a problem.
struct mystr {
char * strp,
unsigned int foo,
};
when you allocated memory using malloc & friends, it only allocates memory for the members.
In your case one char* and one unsigned int. Note that it doesn't allocate any memory for storing data in the char*. So you have to allocate memory for strp again before storing data. Except when you directly assign string literals Or just use the pointer strp to point to an existing memory.
Example:
case 1:
struct mystr s;
s.strp = "literals"; // valid, no need to malloc
case 2:
char *p="abc";
s.strp = p; // valid, no need to malloc
On all other usages, you must allocate memory for strp before storing data into strp.
So when you call free on the struct variable, it only frees the pointer allocated for strp and not the memory which is pointed to by strp.
It's simply because free has no information about where strp points to.
Note that in the above two examples, you don't free strp as you didn't allocate any memory there for storing data into strp. Simple rule is one free for one malloc/calloc/realloc.
C99 says,
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

Understanding concept of free

Tried the following code :
#include<stdio.h>
int main()
{
int *p,*q;
p = (int *)malloc(sizeof(int));
*p =10;
q = p;
printf("%u \n",p);
printf("%u \n",q);
free(p);
printf("%u \n",p);
return 0;
}
The output got is as follows :
[root#lnxdesk Tazim]# ./a.out
154804232
154804232
154804232
Why is that address inside p is still printed even if I have done free(p);?
What has free(p) done then?
I want to understand the concept of free/malloc clearly. Any help will be valuable.
free() only frees the memory on the heap. It does not change the value of your pointer. If you tried to print the memory pointed by your pointer, you'll probably get some kind of garbage.
Also, when you called free, you gave it the pointer, not the address to your pointer, so free can't change your pointer...
That's undefined behavior - once you've freed the pointer the address stored becomes invalid and you can't do anything with it - not only you can't dereference it, but you can't even printf() the pointer value.
You are printing the pointers, i.e. the address of the memory zones allocated for you ints. Freeing a memory zone with free does not set the pointer's address to 0x00 as I think you expect.
It just tells the OS that the memory zone is available again for future re-use.
If you were printing *p after free(p), you would have problems.
malloc() and its ilk reserve space in a memory storage area called the "heap" and return a pointer to that reserved area. So in your sample above p is given a pointer to, probably, a four-byte memory region that has been reserved for its use (whose address happens to be 154804232 this time around). When you do *p = 10 you are now placing the integer value 10 into the memory pointed to. When you do q = p you're now making q point to the same chunk of reserved heap memory.
free() and its ilk just unreserve the memory. When you call free() you're saying "I'm not going to use this memory anymore". All free() does is tell the memory management system that the block of memory is now available for use once again. It emphatically does not change your pointer. It just signals that the block of memory is available. After that it is up to you to ensure that you do not use that pointer again.
If you do use that pointer again it may work fine. Once. Or twice. Or a thousand times. It'll work fine, basically, until you use it after someone else claims that memory block you've said is free and does something with it. When that transpires, Bad Things Happen<tm>. Please don't make bad things happen.
Remember : a pointer is nothing but an address. Before, after your malloc, or free, it'll give you the same result. The only thing that malloc() does is reserve space at this address. The only thing that free does is release it (most probably, mark this address as usable to store other things, "cleaning" would be time consuming).
This is why putting your pointer to NULL after a free is a good idea ; because you can be sure if the pointer is connected to something or not.
free does not reassign the pointer to point to something else. In fact, the C standard
does not mention anything be done with the pointer. This is all it says in the description:
The free function causes the space
pointed to by ptr to be deallocated,
that is, made available for further
allocation. If ptr is a null pointer,
no action occurs. Otherwise, if the
argument does not match a pointer
earlier returned by the calloc,
malloc, or realloc function, or if the
space has been deallocated by a call
to free or realloc, the behavior is
undefined

What is the difference between freeing the pointer and assigning it to NULL?

Could somebody tell me the difference between:
int *p;
p=(int*)malloc(10*sizeof(int));
free(p);
or
int *p;
p=(int*)malloc(10*sizeof(int));
p=NULL;
free will deallocate the memory that p points to - simply assigning it to NULL will not (and thus you will have a memory leak).
It is worth mentioning that it is good practice to assign your pointer to NULL AFTER the call to free, as this will prevent you from accidentally trying to access the freed memory (which is still possible, but absolutely should not be done).
There is no garbage collection in C, so if you don't explicitly free a chunk of memory, it will never get freed, even if there are no references to it. Maybe you come from a background in garbage collected languages, so it might be hard to change your way of thought, but it's always important to remember to "manually" free all resources in low-level languages like C.
Hope this helps
Cheers
p is pointer (to a block allocated dynamically in memory ["on the Heap"])
This means that p is a variable which contains the address in memory of a particular block (or some particular size, in the example a block big enough to hold 10 integers).
free(p); instructs the memory management logic (of the C Runtime) that the memory previously occupied by the block which p points to can be reused.
p = NULL; sets the value of p to NULL (the address it formerly contained is lost) but the block in memory it pointed too is still considered in use.
There can be some confusion because in languages such as Java, C#, Python etc. merely assigning the variable to NULL (or to another address for that matter), will automatically free the underlying memory (assuming no other references to this address exist in other live variables).
This is not the case in C or C++, leading to errors like the following:
free(p);
// possibly some some code etc.
// later:
p[6] = 'a'; // <<--- Ouch we're modifying whatever new variable is there !!!
or
// didn't call free(p)
p = NULL;
// now the memory allocated for p is held in memory even though it
// is not going to be used (assuming no copies of p or of pointers to part
// of that block were made.
The latter case is only wasteful of resources, the former can lead to hard to find bugs.
That's why a typical C idiom is:
free(p);
p = NULL;
Not calling free and directly assigning to NULL will lead to a memory leak as explained by others. You can refer to this link to get clear details about memory leaks and other memory related problems.
The better way is to first free the memory and then set it to NULL:
free(p);
p = NULL;
Freeing the allocated memory deallocates it and allows that memory to be used elsewhere while the pointer to where the memory was allocated is preserved.
Setting a pointer to the allocated memory to NULL does not deallocate it.
If you are using an implementation that uses a heap-based malloc, debug something that allocates, uses and frees memory, and do the same to something that allocates, uses, and sets the pointer to the memory to NULL.
Memory management is implementation-dependent (see http://en.wikipedia.org/wiki/Malloc#Implementations).
1.
int *p;
p= (int * ) malloc(10*sizeof(int));
free(p);
the memory is released back to the heap. but the pointer still pointing to the freed memory location. Thus if its further used , would lead to a memory corruption.
thus correct thing to do is resetting the pointer to NULL explicitly to avoid further usage of that pointer .
its not advisable to type cast the return pointer in C
2.
int *p;
p=(int * )malloc(10*sizeof(int));
p=NULL;
This would result in a memory leak : as the allocated memory is not freed here. you are just reset the pointer to NULL.
p=NULL does not deallocate the memory. If you don't need to use the memory pointed by p anymore you should use free() otherwise there will be memory leak. You should also set p=NULL after calling free() to avoid erroneously accessing that memory again in the future.

Resources