C - memset vs free - c

I am confused on what actually happens in memory when memset is called versus what happens when you call free.
For example I have a pointer A that points to an array of char*'s
char** A = (char**)calloc(5, sizeof(char*));
int i;
for(i=0;i<5;i++)
{
//filling
A[i] = (char*)calloc(30, sizeof(char));
scanf("%s", &A[i]);
}
now I want to reset it my char** pointer and all the elements
it points to be completely empty
memset(A, 0, 5);
or
free(A);
what is the difference?
I am somewhat new to C so please speak in layman's terms thank you

The difference is that memset actually sets the value of a block of memory, while free returns the memory for use by the operating system.
By analogy using physical things, memset(beer, 0, 6) applied to a six-pack of beer would apply the value of '0' to all six members of the array beer, while free(beer) would be the equivalent of giving the six-pack away to a friend.

The memset function sets an area of memory to the requested value. Do note that the size you provide is the number of bytes.
The free function releases the allocated memory so it can't be used anymore. Calling free doesn't usually modify the memory in any way. Using the memory after calling free leads to undefined behavior.

Both approaches are incorrect, but somewhat complementary.
memset will set the content of the buffer to the given value, 0 in your case. This will change the value of the pointers, which will cause you to lose the references to the allocated buffers (in each A[i]).
free(A) will release the buffer pointed by A, but this buffer contains pointers, and each of the buffers that is pointed by them will not be freed.
in short - memset does not free a dynamically allocated buffer, and free does not set it to zero.
A correct approach will be something like that:
for(i=0;i<5;i++)
{
// complementary to
// A[i] = (char*)calloc(30, sizeof(char));
free(A[i]);
}
// complementary to
// char** A = (char**)calloc(5, sizeof(char*));
free(A);
A = NULL; // so no one gets confused...

free deallocates the memory, which means A would still be pointing to the same memory location, which is invalid now.
memset will set the memory currently pointed to by A, to whatever you want.

memset changes the contents at the memory address. It does not alter whether the memory is allocated/deallocated.
free does not change the contents at the memory address. It deallocates the block of memory which makes it available for the program to reclaim and reuse. Therefore any pointers to this block become invalid and trying to access the memory should result in a Segfault ("if you're lucky" as my professor would say).
Use memset when you know you are going to be accessing the data at that address again. Use free when you know that the data will no longer be accessed ever again and that the program may reclaim that memory.

memset() method just replaces the x memory bytes with a given character the allocated memory which is pointed by a pointer *a;
memset(a, 'a', x);
The prototype of memset() method is:
void* memset(void*, unsigned int, int);
memset() behaves like strcpy() but the difference is that memcpy() copied the data as it is (byte), but strcpy copies the formatted string as well (so takes more time than memcpy to execute).
However, free() method just deallocates the memory space and makes it available to get occupied.

While other answers explain the difference, let me add an example when both memset() and free() will need to be used together, in a specific order:
If the malloc'ed memory region was used to store any critical/valuable information that needs to be erased to prevent others from snooping on it (say some security-related stuff like managing a password or some other crypto), you would want to first erase the contents in that memory region and then call free() on it to give away that region's control back to the OS.
Hence, just like free() is the opposite of malloc(), memset(to zero)-then-free() is the opposite of calloc().

Related

Does malloc() reuse the same memory address in loop?

I'm starting to learn C programming and stumbled upon a situation that shows my lack of understanding of how memory allocation with malloc() works.
In a loop like the following:
// will only know `xlen` at runtime so I guess I have to use malloc here
char *x = malloc((xlen + 1) * sizeof(*x));
assert(x != NULL); // memory allocation failed
while (fgets(line, sizeof(line), fp) != NULL) {
strncpy(x, line, xlen); // copy first xlen characters of line
x[xlen] = '\0'; // ensure null terminating string
// do something with x
// x can now be "reused" for another line/loop iteration
// free(x) - errors out with "pointer being freed was not allocated"
}
fclose(fp)
free(x);
If the statement free(x) is called inside the loop then when I run this program I get an error message something like a.out(37575,0x7fff964ce3c0) malloc: *** error for object 0x7fab47c02630: pointer being freed was not allocated.
Why am I seeing this error message and what is causing it?
Will the memory address block of x be "re-used" at each iteration of the loop? (I'd say yes, and that would actually be what I wanted in this case) In this case, is it safe to only free the allocated memory of x outside the scope of the loop?
free(x); frees the memory allocated by char *x = malloc(.... It frees all of the memory, and you don't have to worry about how much memory that was, as it keeps track of that. You just have to call free(x); once as you correctly do. This is why you get the error if you free it inside the loop.
Does it mean that the memory address block of x will be "re-used" at
each iteration? (I'd say yes, and that would actually be what I wanted
in this case)
Yes, you use the same memory. It overwrites the memory every time.
In this case, is it safe to only free the allocated memory of x
outside the loop scope?
Yes, you have to free it outside of the loop. Because if you free it, then all of it is freed. If you did that inside the loop, then it would be undefined behavior to keep accessing that memory in following loop iterations.
The malloc() function provides a pointer to an area of memory that can then be used just like any pointer to a memory location.
The way to think of malloc() and free() is to consider it in terms of who owns a memory area. The malloc() function owns the memory that it is managing. When you call the malloc() function, or calloc() function, the function takes some of the memory it is managing and transfers ownership to you. When the function is called and the memory allocated there is a transfer of ownership from the memory management system of malloc() to you and at that point you own that memory and it is up to you to manage it. When the free() function is called to release the memory, you are transferring ownership of the memory area from you back to the memory management system of malloc().
Whenever a transfer of ownership is done, the entity that is giving up ownership is not supposed to do anything further with the memory area since it no longer owns it.
So when you do the malloc() you now own the memory and can use and reuse the memory area as much or as little as you want until such time that you call the free() function to give it back to malloc().
A pointer to a memory region given by malloc() is like any other pointer so far as using it is concerned.
Once you have transferred ownership of a memory area back to malloc() by using thee free() function, you can't call free() again with the same pointer without introducing an error. Once a memory area has been returned using free() you no longer have ownership of the memory so you shouldn't try to do anything else with it and that includes calling free() with the pointer again.
How malloc() manages memory is an implementation detail that will vary depending on the compiler and the C Runtime used. In some cases if you malloc() memory then free() the memory and then malloc() the same amount of memory again you may get lucky and get the same memory area again however it is not something you can count on or should expect.
malloc() provides you a pointer to a memory area that has a couple of guarantees. First of all the memory area provided will be at least as large as you requested. It may be larger but it won't be smaller than what you requested. Secondly the address provided will be on a memory boundary suitable for the machine architecture so that you can use the address provided for any variable type whether a built in such as int or double or a struct or an array of some type.
As the owner of the memory area provided by malloc() you are responsible for giving the memory area back to the malloc() functionality once you are done with it.
Your other primary responsibility is to respect the size of the memory area and to not write a larger data block into the area than the size requested when the malloc() was done. You are guaranteed only the amount of memory requested and writing a larger block of data into the memory will probably overwrite memory that you do not own but is owned by something else.
Unfortunately because the malloc() functionality, at least the optimized or non-debug version of the library, is designed with little as possible overhead, the functionality has few consistency and sanity checks in place. The malloc() functionality trusts that you will obey the rules and guidelines and only use what you own. And often when you break the rules and guidelines, you won't see the effect at the point where you have made a mistake but rather at some other point when some mysterious memory corruption is discovered and your program crashes.
You can use and reuse dynamically allocated memory as long as you have not called free() on it. If you free it and attempt to use it again, then you will have undefined behaviour.
You can continue to reusing memory (eg buf created by char *buf = calloc(sizeOfBuf); ) allocated to you on a single call to calloc(), until free(buf) is called, just as if buf was created statically, eg char buf[sizeOfBuf]; = 0. However, if the size of the buffer initially created by using calloc() needs to change, realloc() is available to do this, and is the preferable method. There are some caveats about using realloc however. Here is an example of using realloc, this one packaged into a function that resizes an existing dynamically allocated buffer, and takes care of some of the caveats:
realloc usage example:
// initial call to calloc
char *buf = calloc(sizeOfBuf);
if(buf)
{
while(someConditionIsTrue)
{
// read new content
//...
//new content needs to be added to buf
char *tmp = realloc(buf, newSizeOfBuffer);
if(!tmp)//if failed...
{
free(buf);//... free original buf to prevent memory loss
return NULL;// return null, caller must test for this
}
buf = tmp;//...else copy new mem location back to original pointer
//continue doing stuff with buf
}
//when done with buf, free it
free(buf);
}
One other suggestion, consider calloc() returns uninitialized memory, i.e. you own a space that contains whatever was occupying it when it was given to you. It is a good idea to follow that command with a method to clean up the buffer:
memset(buf, 0, sizeOfBuf);
Or use calloc().

Correct use of free() when deallocating a 2d matrix in c

I'm just starting to learn coding in c, and I have a few questions regarding 2d matrices in combination with the free() command.
I know that you first need to create an array with pointer, pointing to the different columns of the matrix:
double **array = (double **)malloc(5*sizeof(double *));
for(int n = 0; n<5; n++){
array[n] = (double *) malloc(6*sizeof(double));
I know that the correct way to then deallocate this matrix is to first deallocate the individual rows and then the array pointer itself. Something along the lines of:
for (i = 0; i < nX; i++){
free(array[i]); }
free(array);
My question is: Why is this necessary? I know that this incorrect, but why can't you just use: free(array)? This would deallocate the pointer array, to my understanding. Won't the memory that is used by the columns just be overwritten when something else needs acces to it? Would free(array) lead to corrupted memory in any way?
Any help is much appreciated!
Your code, not only allocate memory for array of pointers (the blue array), but in the for loop, you also allocate memory for the red arrays as well. So, free(array) line, alone, will just free the memory allocated by the blue array, but not the red ones. You need to free the red ones, just before loosing the contact with them; that is, before freeing the blue array.
And btw;
Won't the memory that is used by the columns just be overwritten when something else needs acces to it?
No. The operating system will keep track of the memory allocated by your process (program) and will not allow any other process to access the allocated memory until your process terminates. Under normal circumstances —I mean, remembering the C language not having a garbage collector— the OS never knows that you've lost connection with the allocated memory space and will never attempt like, "well, this memory space is not useful for this process anymore; so, let's de-allocate it and serve it for another process."
It would not lead to corruption, no, but would create a memory leak.
If done once in your program, it probably doesn't matter much (a lot of professional/expensive applications have - small,unintentional - memory leaks), but repeat this in a loop, and you may run out of memory after a while. Same thing if your code is called from an external program (if your code is in a library).
Aside: Not freeing buffers can be a useful way (temporarily) to check if the crashes you're getting in your programs originate from corrupt memory allocation or deallocation (when you cannot use Valgrind). But in the end you want to free everything, once.
If you want to perform only one malloc, you could also allocate one big chunk, then compute the addresses of the rows. In the end, just deallocate the big chunk (example here: How do we allocate a 2-D array using One malloc statement)
This is needed because C does not have a garbage collector.
Once you allocate memory with malloc or similar function, it is marked as "in use" for as long as your program is running.
It does not matter if you no longer hold a pointer to this memory in your program.
There is no mechanism in the C language to check this and automatically free the memory.
Also, when you allocate memory with malloc the function does not know what you are using the memory for. For the allocator it is all just bytes.
So when you free a pointer (or array of pointers), there is no logic to "realize" these are pointers that contain memory addresses.
This is simply how the C language is designed: the dynamic memory management is almost1 completely manual - left to the programmer, so you must call free for every call to malloc.
1 C language does handle some of the more tedious tasks needed to dynamically allocate memory in a program such as finding where to get a free continuous chunk of memory of the size you asked for.
Let's take this simple example:
int **ptr = malloc(2*sizeof *ptr);
int *foo = malloc(sizeof *foo);
int *bar = malloc(sizeof *bar);
ptr[0] = foo;
ptr[1] = bar;
free(ptr);
If your suggestion were implemented, foo and bar would now be dangling pointers. How would you solve the scenario if you just want to free ptr?

Freeing portions of dynamically allocated blocks?

I was curious whether there exists a dynamic memory allocation system that allows the programmer to free part of an allocated block.
For example:
char* a = malloc (40);
//b points to the split second half of the block, or to NULL if it's beyond the end
//a points to a area of 10 bytes
b = partial_free (a+10, /*size*/ 10)
Thoughts on why this is wise/unwise/difficult? Ways to do this?
Seems to me like it could be useful.
Thanks!
=====edit=====
after some research, it seems that the bootmem allocator for the linux kernel allows something similar to this operation with the bootmem_free call. So, I'm curious -- why is it that the bootmem allocator allows this, but ANSI C does not?
No there is no such function which allows parital freeing of memory.
You could however use realloc() to resize memory.
From the c standard:
7.22.3.5 The realloc function
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size. The contents of the new object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.
There is no ready-made function for this, but doing this isn't impossible. Firstly, there is realloc() . realloc takes a pointer to a block of memory and resizes the allocation to the size specified.
Now, if you have allocated some memory:
char * tmp = malloc(2048);
and you intend to deallocate the first, 1 K of memory, you may do:
tmp = realloc(foo, 2048-1024);
However, the problem in this case is that you cannot be certain that tmp will remain unchanged. Since, the function might just deallocate the entire 2K memory and move it elsewhere.
Now I'm not sure about the exact implementation of realloc, but from what I understand, the code:
myptr = malloc( x - y );
actually mallocs a new memory buffer of size x-y, then it copies the bytes that fit using memcpy and finally frees the original allocated memory.
This may create some potential problems. For example, the new reallocated memory may be located at a different address, so any past pointers you may have may become invalidated. Resulting in undefined runtime errors, segmentation faults and general debugging hell. So I would try to avoid resorting to this.
Firstly, I cannot think of any situation where you would be likely to need such a thing (when there exists realloc to increase/decrease the memory as mentioned in the answers).
I would like to add another thing. In whatever implementations I have seen of the malloc subsystem (which I admit is not a lot), malloc and free are implemented to be dependent on something called as the prefix byte(s). So whatever address is returned to you by malloc, internally the malloc subsystem will allocate some additional byte(s) of memory prior to the address returned to you, to store sanity check information which includes number of allocated bytes and possible what allocation policy you use (if your OS supports multiple mem allocation policies) etc. When you say something like free (x bytes), the malloc subsystem goes back to peek back into the prefix byte to sanity check and only if it finds the prefix in place does the free successfully happen. Therefore, it will not allow you to free some number of blocks starting in between.

How to realloc() in the middle of an array?

I have an array of pointers
char *wordlist[9];
and then I malloc() a block of memory on every of this pointers
for(int i=0; i<9; i++)
wordList[i] = (char*)malloc(someLength);
Lets suppose that every time the someLength is different.
And the problem is now, that I want to realloc() ie. 4th elemet of wordList to a larger size than it is now.
wordList[3] = (char*) realloc(&wordList[3], someBiggerSize);
Since malloc allocates a consistent block of memory, is that operation even possible without colliding with wordList[4]?
There's nothing to worry about this in principle. You just have an array of pointers and each element of the array points to a distinct memory block. Each element of the array, each pointer, can be therefore be reallocated independent of the other elements.
Now, I say in principle because your code does have an error. You should pass wordList[3] rather than &wordList[3] to the realloc.
Just remove the & . wordList[3] = (char*) realloc(wordList[3], someBiggerSize);
wordList[3] is a pointer, and realloc expected to get a pointer that allocated by malloc. not pointer to it.
About your last question: every time you call malloc, it return a consistent block of memory. there is not guarantee that memory, allocated by two calls for malloc, will be consistent. In other words, wordList[3] and wordList[4] are not must be consistent, and you can do whatever you want two one of them (as long as you care about the buffers size) without thinking about the other.
Why should it be colliding? You have declared an array of pointers, each of which points to memory that is allocated elsewhere. When you reallocate you are just changing the size/position of this memory, the pointer returned by realloc is as big as it was.
By the way, you shouldn't be using realloc that way, since, if it fails, you'd be leaking memory; see e.g. here.
---edit---
And, as #asaelr noted, you should remove that &, just reallocing the block pointed by wordList[3], not the memory of wordList.
You have a misunderstanding about what realloc does. It will return a whole new block of memory (if the new size is larger than the old size) instead of increasing the size of the block that was passed into it.
malloc allocates a trunk of memory from heap and that trunk of memory can't be allocated for other malloc until you free them. In other words, malloc succeeds only if there are enough continuous free space in the heap. So this makes sure that the memory allocated would not collide with any others in your words.
Each of your pointers points to a separate and independent block of memory. Inside your array of pointers, each element is simply an address and overwriting one won't affect the others. So, what you are doing is fine and won't cause any problems with other elements of the array. As others mentioned, you should be passing wordList[3] and not &wordList[3]

Instead of just using free() and having the pointer pointing some new block, how to really empty the previously-pointed-at memory block?

I am trying to free dynamically allocated memory using free(), but I found that what it does is to have the argument pointer point to some new location, and leaving the previously-pointed-at location as it was, the memory is not cleared. And if I use malloc again, the pointer may point to this messy block, and it's already filled with garbage, which is really annoying..
I'm kinda new to C and I think delete[] in c++ doesn't have this problem. Any advise?
Thanks
By free the memory is just released from use. It is released from being allocated to you. it is not explicitly cleared. Some old contents might be present at those memory locations.
To avoid this, there are two solutions.
Solution 1:
You will need to do a memset after allocating memory using malloc.
Code Example:
unsigned int len = 20; // len is the length of boo
char* bar = 0;
bar= (char *)malloc(len);
memset(bar, 0, len);
Solution 2:
Or use, calloc() which initiliazes memory to 0 by default.
Code Example:
int *pData = 0;
int i = 10;
pData = (int*) calloc (i,sizeof(int));
I think delete[] in c++ doesn't have this problem.
No
It behaves exactly this same way. Unless you explicitly set the pointer to 0 the delete'd pointer will not be pointing to 0. So do always set the pointer to 0 after you delete it.
When should you use malloc over calloc or vice versa?
Since calloc sets the allocated memory to 0 this may take a little time, so you may probably want to use malloc() if that performance is an issue.(Ofcourse One most profile their usage to see if this really is a problem)
If initializing the memory is more important, use calloc() as it does that explicitly for you.
Also, some OS like Linux have an Lazy Allocation memory model wherein the returned memory address is a virtual address and the actual allocation only happens at run-time. The OS assumes that it will be able to provide this allocation at Run-Time.
The memory allocated by malloc is not backed by real memory until the program actually touches it.
While, since calloc initializes the memory to 0 you can be assured that the OS has already backed the allocation with actual RAM (or swap).
How about realloc?
Yes, similar behavior to malloc.
Excerpt From the documentation:
void * realloc ( void * ptr, size_t size );
Reallocate memory block
The size of the memory block pointed to by the ptr parameter is changed to the size bytes, expanding or reducing the amount of memory available in the block.
The function may move the memory block to a new location, in which case the new location is returned. The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved.If the new size is larger, the value of the newly allocated portion is indeterminate.
In case that ptr is NULL, the function behaves exactly as malloc, assigning a new block of size bytes and returning a pointer to the beginning of it.
In case that the size is 0, the memory previously allocated in ptr is deallocated as if a call to free was made, and a NULL pointer is returned.
You can use calloc( ) instead of malloc( ) to clear the allocated memory to zero.
Why is having newly allocated memory filled with garbage "really annoying"? If you allocate memory, presumably it's because you're going to use it for something -- which means you have to store some meaningful value into it before attempting to read it. In most cases, in well-written code, there's no reason to care what's in newly allocated memory.
If you happen to have a requirement for a newly allocated block of memory you can call memset after calling malloc, or you can use calloc instead of malloc. But consider carefully whether there's any real advantage in doing so. If you're actually going to use those all-bits-zero values (i.e., if all-bits-zero happens to be the "meaningful value" I mentioned above), go ahead and clear the block. (But keep in mind that the language doesn't guarantee that either a null pointer or a floating-point 0.0 is represented as all-bits-zero, though it is in most implementations they are.)
And free() doesn't "have the argument pointer point to some new location". free(ptr) causes the memory pointed to by ptr to be made available for future allocation. It doesn't change the contents of the pointer object ptr itself (though the address stored in ptr does become invalid).

Resources