How does free () frees memory when 0 is encountered? - c

I have a question, about C-function free().
What will happen, if first I'll allocate memory for char-string, then past '\0' to any position of the string and set the new pointer to the next after '\0' position?
If after I will try use free on the initial pointer, is there a memory leak? Or compilator knows termination position and free all of the allocated memory?
Manuals say "Frees the pointer, allocated by malloc", but I still have no full understanding of this process.
There's an example:
#include "stdlib.h"
int main()
{
int i = 0;
char* test = (char*)malloc(sizeof(char) * 100);
char s = 'a';
for (int i = 0; i < 10; i++)
test[i] = s;
test[10] = '\0';
char* v = (test + 6);
test[4] = 0;
free(test);
return 0;
}
Valgrind says:
Address 0x522d048 is 8 bytes inside a block of size 100 free'd

malloc reserves memory for your use and returns a pointer to that memory. Internally, malloc remembers information about that memory. In particular, it remembers how much it reserved.
When that same pointer is passed to free, free terminates the reservation.
Once that reservation is ended, you should not use any of that memory. In your example, when you call free(test), all of the memory that was reserved by malloc(sizeof(char) * 100) is released. The fact that you put a null character in part of it and have data later after is irrelevant. The fact that you still have a pointer v that points to somewhere in the memory is irrelevant. free releases all of the memory that was allocated, regardless of contents.
(This does not mean that attempting to use the memory will not work. After you call free, the memory is no longer reserved for you to use. But it is possible that nothing will act to prevent you from using it—no trap is guaranteed to occur if you try. But it is also possible that a trap might occur or that other software in your program might use that memory, so your use of it could interfere.)

Memory allocation with malloc allocates the number of bytes requested and returns a pointer to the beginning of the allocated range.
Function free() deallocates the range only when you pass the pointer returned by malloc. Any other pointer passed to free invokes "undefined behavior".
Neither function knows or cares what information you place in the range of allocated bytes.
Moreover, freeing a NULL pointer does nothing since according to the standard value of NULL is internally checked.

Related

Assigning pointer to string in c

char* get_string() {
char * a = malloc(sizeof(char)*5);
a = "asdf";
return a;
}
Can someone please explain why this function would cause memory leak?
You first initialized a with a pointer to a location in memory. Then you re-assign a to another pointer to location occupied by string asdf, so you lost the first pointer to the allocated memory. you can never free them since you lost track of the 5 bytes memory allocated by malloc initially.
You leak that 5 bytes of memory here.
If you want to copy asdf to the memory pointed by a, you can use strcpy.
strcpy(a, "asdf");
In this way, you need to call free in your code somewhere to avoid leaks.
Short answer:
char * a = malloc(sizeof(char)*5);
you allocated memory here from the heap, a has an address in the heap (say 0x1234EEEE) pointing into dynamic memory. You need to free this allocation when done, else a memory leak happens.
then
a = "asdf";
now you have assigned a as pointing to static compile time memory location where the string "asdf" is stored (say 0x0BADBEEF, it's not in the dynamic heap). You no longer know where the hell you allocated memory from the malloc call above (it was at 0x1234EEEE, but now you have no reference to it), therefore you can never free() it ... that's a leak;
"char *a;"
a here is a pointer, it can point to anything.
"a = (char *)0x0000"
should be valid, but not logical;
"long l = 12345L;
a = (char *)&l;"
this should be legal also, but not logical
"asdf" is a static string in your example, it is stored in compile time allocated memory. You can just "return("asdf");" from your function, understanding it is in a statically allocated memory space defined at compile time. Working with pointers without understanding logical memory layouts will have ramifications you may soon learn ;~).

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.

C - memset vs free

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().

How to free a char* that is being returned from another function?

Let's say we have the following scenario.
char* halfString(char* input) {
char* output = malloc(strlen(input));
int i = 0;
for(i = 0; i < strlen(input); i++)
output[i] == input[i];
output[i] = '\0';
return output;
}
int main() {
char* input = "Hello";
char* output = halfString(input);
printf("%s\n",output);
free(output);
}
Will the call "free(output)" free the memory of char* output that is local to main and free the memory of the char* output local to halfString()? OR is there still a memory leak for the char* output local to halfString()?
Any help is appreciated.
There is no memory leak.
You seem to be confused, though, about how heap allocation works. There is only one chunk of memory being allocated here, and it is not "local" to either halfString() or to main(). The allocated chunk exists in the heap, and is not scoped to a particular code block.
malloc() returns a pointer to it. You then return that pointer back to main(), but the value of the pointer is still the same: it points to the same address in memory, the same chunk of heap. main() then properly frees it.
As a design consideration, this is often not the best thing to do. In general, a caller may not necessarily know that the pointer returned by halfString() points to a chunk that was allocated with malloc() and that they need to free() it. This would have to be very clearly and carefully documented. A better solution might be to provide a freeHalfString() function which does the freeing; then from a maintenance standpoint, those two functions can be put in the same place and maintained concurrently, so that the caller doesn't need to worry about how the buffer was allocated, or how to free it.
(As others have pointed out, you also have a buffer overflow because you need to allocate strlen(input) + 1 bytes to include the NULL terminator.)
The code is mostly correct, because malloc() puts memory on the heap and free() frees it. It does not matter which functions they get called from.
That said, there is an important off-by-one error:
char* output = malloc(strlen(input) + 1); // Don't forget +1
The strlen() function returns the number of characters in the string, not including the terminator.
These errors can be often caught automatically by using certain tools like Mudflap (compile with -fmudflap, if using GCC) and Valgrind.
Algorithmic complexity
There is a problem with the algorithmic complexity of your code, which will probably disappear with good compilers when optimization is enabled.
for(i = 0; i < strlen(input); i++)
This will call strlen(), which is O(N), and it will call strlen() O(N) times, giving O(N2) asymptotic performance. We can do better, here are two fixes:
// Version 1
size_t i, n = strlen(input);
for (i = 0; i < n; i++)
...
// Version 2
size_t i;
for (i = 0; input[i] != '\0'; i++)
...
You seem to be confusing two related items: buffers, and pointers. A buffer is a block of memory which, in the context of your question, is allocated using malloc(). A pointer is related in that it points to a buffer, but it's not the buffer itself.
In your halfString() function, you allocate a buffer, and you store the address of (pointer to) that buffer in your local output.You then return it to the caller, main(), which coincidentally has a variable of the same name which will point to the same buffer.
Now, in main(), when you free(output); you're not freeing a pointer, you're freeing the buffer that pointer points to. It doesn't matter where the buffer was allocated, it only matters that the buffer was allocated (and not already freed). After this call your main function's output variable still exists, and it still has an address to what was once a valid buffer -- but that buffer must not be used of course, since it's no longer valid.
Now as to your question "Is there a memory leak?" -- You've malloc'd a single buffer, then you free'd that same buffer, so no link. Always properly pair a malloc with a free, and you'll be in good shape.
The free() will free the memory allocated in called function itself. it is not local to any function because malloc allocates memory on heap.
what you call as local memory is on stack that will be freed when function returns.
So what allocation done using malloc is on heap and the procedure you used will free memory allocated in called function.
This code will work correctly (if the off-by-one error others mention is fixed). The call in main will free the memory allocated in halfString.
There is no "memory of output that is local to main". What is local to main is the output pointer, which was allocated on the stack and will go out of scope when main exits.
There is no memory leak. System knows how much memmory is associated with pointer, and since you can not free part of memory block allocated with malloc, it will free all.

Why does free() need the starting pointer of a dynamic array?

If I run this code it will crash with a stack dump:
int * a = (int *) malloc(sizeof(int) * 10);
a++;
free(a);
Why doesn't it work?
Why does it need the pointer returned by malloc()?
What records does the resource management system behind it keep?
Is it the length of the array? Is it the last cell's address? And does it associate it with the starting pointer?
When memory is allocated, the size of allocated memory is stored in a block adjacent to the allocated block.
Why doesn't it work?
int * a = (int *) malloc(sizeof(int) * 10);
a++;
free(a);
This will not work because, free searchs for the adjacent block which has the size of allocated memory.
Why does it need the pointer returned by malloc?
The adjecent block of pointer returned by malloc, has the information about the size of allocated memory.
It doesn't work because you add one to the pointer that malloc returned to you.
free expects a pointer that malloc returned. Due to the a++ the pointer is no longer what malloc returned and thus free doesn't know what to do with it.
The malloc function reserves a little bit more memory in the heap than what the user tells it. This is because a unique value before the allocated blocks is saved in order to know what size and chunks of memory the system is able to free.
int * a = (int *) malloc(sizeof(int) * 10);
When you increment the pointer "a", the system will refer to the new location that a is pointing to and therefore it results in reading garbage data.
This leads to usually undefined behavior and usually causes crashing when running your program.
Malloc usually allocates more data than what we usually request. This additional space is used to house some of the important information such as the amount of memory(number of bytes) allocated when a malloc call is made. Sometimes additional information such as pointer to the next free location is also maintained. This information is stored at a specific location relative to the starting memory location that malloc return to us. If we return some other address to the free function, then it will look at the value in the address relative to what you passed to free and will end up freeing that number of bytes and "may" cause a crash.

Resources