char* to char[] - free necessary? - c

assume the following scenario:
while(!notTheEnd) {
char str[1024];
char* ptr_to_str;
/* some strcat, strcpy on str */
ptr_to_str = str;
chmod(ptr_to_str, 0777);
}
Do I have to set the char* ptr_to_str = NULL and free it to avoid memory leak ?
Just a theoretical question I was thinking of.

You only have to free() what you have malloc()ed. Therefore: No.
See also the manpage for free():
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.
Note that other functions may use malloc() or alike internally thus also requiring the returned buffer to be free'd (e.g. strdup).
Setting the pointer to NULL is not required at all. It however adds some convenience as subsequent calls to free() on this pointer will not expose the application to undefined behavior. And, if done consistently, you can check whether the pointer indeed points to an object or not.

You never called malloc() so you don't need to call free().
What you have is an pointer to an character array on stack, it does not need explicit deallocation.

No, as long as you don't allocate memory (on heap) you don't need to free it. There are some exceptions (such as strdup), but this is the general rule.

char str[1024] will allocate 1024 bytes in current stack. And this space will be automatically "popped out" when function returns. So you don't need to explicitly free this memory.

Related

Calling free on a pointer to an element of an array declared dynamically

When I run the following code:
int main(int* argc, char** argv) {
int* array = malloc(5 * sizeof(int));
free(array + 3);
}
I get the error pointer being freed was not allocated. My intuition is that instead of trying to free the fourth element of array, free tried to free the thing living 3*sizeof(int) bytes after its last element. Is this correct? If so, then why does this happen? And is the behaviour resulting from the execution of this programme always predictable, or is it undefined of implementation-specific?
free expects you to use the very same address returned from malloc or otherwise anything might happen. The malloc call allocates a whole segment per call, in this case 5 int large. It doesn't make sense to free up parts of this segment, that's not how the heap works.
Heaps first allocate a segment header which is internal information that contains size etc. Then after that header, all the data. This header part isn't visible to the programmer and how it is implemented is OS and/or C library specific.
Indeed in your case you pass an address which sits 3*sizeof(int) bytes into the data part of the segment, which isn't a valid address since free needs the initial address used by malloc in order to know where the internal header of that segment starts. When you pass the wrong address to it, it might grab some other part of random data and treat that as the header. The behavior is undefined.
(You can however pass a null pointer to free() and that's guaranteed to be a no-op.)
From specification of free():
Synopsis
#include <stdlib.h>
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 a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
Thus, what you're trying to do is undefined behavior
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf
malloc allocates a block of memory.
You can only de-allocate (free) this block. You cannot free individual elements or a part of the block.
You can re-allocate (realloc) this block to make it larger or smaller.

Should I call free when creating a new pointer pointing to an area originally created by malloc

In the code below, do I need to "free" the pointer pointing to an area of memory that was allocated using malloc? Isn't it sufficient to free the main pointer?
char * parentArray = malloc( 10 * sizeof(char));
char * miniArray = &parentArray [1];
free(myArr);
// free(miniArray) ?
In your code, parentArray is the value returned by malloc and this is the value that needs to be passed to free. The family of functions in C that perform dynamic memory allocation are: malloc, calloc, and realloc. Calling free on a value not returned by one of these functions or calling free on the same value twice is undefined behavior.
There do exist other functions such as strdup that call malloc and return the result, so these pointers must be freed too. The documentation for strdup will tell you this. In general when writing C you must understand who is responsible for allocating and freeing memory and make sure this "contract" is well documented.
char * miniArray = &parentArray [1];
Here you're not allocating memory, instead you're just making miniArray point to some address.
There is no need for free for miniArray hence.
However dereferecing miniArray should not be done after free(parentArray). That results in undefined behavior, ie you should not do
*miniArray
later in your code.
free() deallocates the space previously allocated by malloc(), calloc() or realloc() otherwise the behavior is undefined.
From C Standard##7.22.3.3p2
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.
In your code snippet, parentArray is allocated memory using malloc()
but here:
char * miniArray = &parentArray [1];
miniArray is pointing to address of the first element of parentArray which is a valid memory but not the pointer returned by malloc(). Hence, calling free for miniArray would be undefined behavior.
parentArray references dynamic memory allocated by malloc(); nothing else your code snippet does.
Each allocation provided by malloc(), calloc() or realloc() should be freed once and only once; multiple references to the same allocation must only be freed once.
A brief example:
void *a=malloc(size); // a references heap mem allocation
void *b=a; // b references heap mem allocation
free(a); // heap mem allocation freed
free(b); // error: heap mem allocation already freed

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.

Query related to free() in C

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.

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