Imagine this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRSIZE 2048
int main()
{
char *str;
str = get_string();
return 0;
}
char * get_string()
{
char temp[MAXSTRSIZE], *str;
fgets(temp,MAXSTRSIZE,stdin);
str = malloc( sizeof(char) * (strlen(temp) + 1) );
strcpy(str, temp);
return str;
}
Do I need to free() the temp variable in function get_string?
What if did the get_string code inside the main()?
free call applies only for dynamically allocated memory and not for static memory allocations
so if there is anything allocated dynamically using malloc/calloc needs to be freed when ever the reference count to the specified memory block will reach to zero, on the other hand statically allocated memory must not be freed at all, the program itself I suppose will not have right to free the memory allocated statically
in case you try to free static memory compiler ideally throws a warning at compile time like below
warning: attempt to free a non-heap object
in case, where the warning is ignored will present a nice runtime crash at free
* glibc detected ./a.out: free(): invalid pointer:*
never attempt to free a non-heap object
The caller will need to make sure str is freed. temp was not dynamically allocated, so you cannot free it.
You must free() whatever you malloc(), it does not matter when or where but it must be happen to prevent a memory leak. When free() is called, the pointer must not be dereferenced again.
Note that get_string() must be declared or defined prior to main().
You do not need to (MUST NOT) free the temp variable, but you need to free str in your main (as it's malloced in get_string).
Related
#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! :)
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.
Does strdup allocate another memory zone and create another pointer every time?
For example: does the following code result in a memory leak?
void x(char** d, char* s){
*d = strdup(s);
}
int main(){
char* test = NULL;
x(&test, "abcd");
x(&test, "etc");
return 0;
}
Yes, the program leaks memory because it allocates objects and then loses references to them.
The first time this happens is in the line:
x(&test, "etc");
The variable test holds the one and only copy of a pointer that was allocated in a previous call to x. The new call to x overwrites that pointer. At that point, the pointer leaks.
This is what it means to leak memory: to lose all references to an existing dynamically allocated piece of storage.*
The second leak occurs when the main function returns. At that point, the test variable is destroyed, and that variable holds the one and only copy of a pointer to a duplicate of the "etc" string.
Sometimes in C programs, we sometimes not care about leaks of this second type: memory that is not freed when the program terminates, but that is not allocated over and over again in a loop (so it doesn't cause a runaway memory growth problem).
If the program is ever integrated into another program (for instance as a shared library) where the original main function becomes a startup function that could be invoked repeatedly in the same program environment, both the leaks will turn into problems.
The POSIX strdup function behaves similarly to this:
char *strdup(const char *orig)
{
size_t bytes = strlen(orig) + 1;
char *copy = malloc(bytes);
if (copy != 0)
memcpy(copy, orig, bytes);
return copy;
}
Yes; it allocates new storage each time.
If you have a garbage collector (such as Boehm) in your C image, then it's possible that the leaked storage is recycled, and so strdup is able to re-use the same memory for the second allocation. (However, a garbage collector is not going to kick in after just one allocation, unless it is operated in a stress-test mode for flushing out bugs.)
Now if you want to actually reuse the memory with realloc, then you can change your x function along these lines:
#include <stdlib.h>
#include <string.h>
void *strealloc(char *origptr, char *strdata)
{
size_t nbytes = strlen(strdata) + 1;
char *newptr = (char *) realloc(origptr, nbytes); /* cast needed for C++ */
if (newptr)
memcpy(newptr, strdata, nbytes);
return newptr;
}
(By the way, external names starting with str are in an ISO C reserved namespace, but strealloc is too nice a name to refuse.)
Note that the interface is different. We do not pass in a pointer-to-pointer, but instead present a realloc-like interface. The caller can check the return value for null to detect an allocation error, without having the pointer inconveniently overwritten with null in that case.
The main function now looks like:
int main(void)
{
char *test = strealloc(NULL, "abcd");
test = strealloc(test, "etc");
free(test);
return 0;
}
Like before, there is no error checking. If the first strealloc were to fail, test is then null. That doesn't since it gets overwritten anyway, and the first argument of strealloc may be null.
Only one free is needed to plug the memory leak.
* It's possible to have a semantic memory leak with objects that the program hasn't lost a reference to. For instance, suppose that a program keeps adding information to a list which is never used for any purpose and just keeps growing.
Yes, it allocates memory and leaks if you don't free it. From the man page:
The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).
new_s = strdup(s) is essentially equivalent to:
new_s = malloc(strlen(s)+1);
strcpy(new_s, s);
Consider the following definition for strdup:
#include <string.h>
char *strdup(const char *string);
strdup reserves storage space for a copy of string by calling malloc. The string argument to this function is expected to contain a null character (\0) marking the end of the string. Remember to free the storage reserved with the call to strdup.
You must free the string yourself.
I came across an issue that I am not sure if it's an issue at all. I have a simple C funcion that gets a char* passed from string like so:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
passString("hello");
return (EXIT_SUCCESS);
}
void passString(char * string) {
// .... some code ....
free(string); // ???
}
and I was taught to free every memory block that I'm not working with anymore (mainly arrays). So my though was to free string as well but the program freezes or crashes even with this simple example. I'm not sure whether I really need to free string here or not and if so how do I achieve that?
You do not need to free memory which you did not allocate with malloc.
In your example string is not allocated by malloc in your program so you do not need to free it. string is a string literal and is allocated somewhere in the read-only memory(implementation defined) and is automatically freed.
For standerdese fans:
References:
c99 Standard: 7.20.3.2 The free function
Synopsis
#include
void free(void *ptr);
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.
Returns
The free function returns no value.
The string you're freeing is statically allocated, "during compilation" if you will. Indeed any string literal ("hello") is done this way. You cannot free statically allocated memory as it does not live in the heap.
As a general rule, it's actually better to free at the point of allocation. In this case, were you to dynamically allocate space for "hello", you would do this:
int main(int argc, char** argv) {
char *s = strdup("hello");
passString(s);
free(s);
return (EXIT_SUCCESS);
}
void passString(char * string) {
// .... some code ....
}
You only need to free what you've allocated dynamically (via malloc in C or via keyword new in C++). Basically, for any allocation call like malloc() there should be a free() somewhere.
String literals aren't dynamically allocated and you don't need to be concerned about them.
What happens if you try to free a memory which is not allocated using malloc/calloc?
Here is what I mean :
void main()
{
int temp = 0;
int *ptr = &temp;
free(ptr);
}
I thought free() would return some error code but free() does not have a return value.
If you call free() on the pointer which wasn't allocated before, it will trigger undefined behavior.
From Linux man pages:
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous 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.
To add to Malcolm's answer: This is undefined behavior by ISO/IEC 9899:1999, 7.20.3.2:
Otherwise, if the argument does not match a pointer earlier returned by the
calloc, malloc, or realloc function [...] the behavior is undefined.
See the draft standard here: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf.
I extended the above code a bit:
#include <stdio.h>
#include <stdlib.h>
void main()
{
int temp = 0;
int *ptr = &temp;
printf("Before: %0X\n", ptr);
free(ptr);
printf("After: %0X\n", ptr);
getchar();
}
If this code is compiled by Visual Studio 2010, in Debug configuration, calling free initiates a "Debug Assertion failed" message. This error message comes from dbgheap.c:
/*
* If this ASSERT fails, a bad pointer has been passed in. It may be
* totally bogus, or it may have been allocated from another heap.
* The pointer MUST come from the 'local' heap.
*/
_ASSERTE(_CrtIsValidHeapPointer(pUserData));
Compiling with MinGW-GCC, the resulting exe runs without error (the "After: ..." line shows the same value for ptr as the "Before: ..." line).
All hell will break loose.
Which means:
If you are lucky, your program will error out and terminate.
If you are not lucky, some attacker will execute arbitrary code using your program (free() will usually try to insert your newly freed "chunk" of memory into some data structure, which usually involves some writes at locations determined by values at/near the pointer you passed).
Anything between these two extremes. Not terminating in error should be considered worse than terminating in error.
In addition to the answers by Malcom and undur_gongor, C on Windows with Visual Studio is the same. The pertinent section from MSDN's description is found here:
The free function deallocates a memory block (memblock) that was previously allocated by a call to calloc, malloc, or realloc. The number of freed bytes is equivalent to the number of bytes requested when the block was allocated (or reallocated, in the case of realloc). If memblock is NULL, the pointer is ignored and free immediately returns. Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors.