so I have another newbie question for you. This function is meant to read all the bytes from a passed in file, store them in the heap and then store the address to those bytes in the passed in 'content' parameter and the length in the passed in 'length' parameter.
bool load(FILE* file, BYTE** content, size_t* length)
{
if (file == NULL)
{
return false;
}
//array to hold the bytes??
BYTE* buffer = malloc(sizeof(BYTE));
//To hold the number of bytes currently loaded
size_t size = 0;
//Pointer to keep track of where I am adding the data to in buffer
//get all the bytes from the file and put them in the buffer
for(int i = fgetc(file); i != EOF; i = fgetc(file))
{
buffer[size] = (char) i;
size++;
buffer = realloc(buffer, size + 1);
}
//dereference length
*length = size;
//derefernce content
*content = buffer;
//free(buffer);
return true;
}
So previously the larger program that this function was a part of did not work, yet when I commented out the
free(buffer);
call at the bottom my program started to work perfectly. I was motivated to comment this out when I came across a double free error. So my question is: why does calling free in this instance cause an error?
My intuition tells me that it is because the data that
*content
points to is now "deleted" and so my program wasn't working. Furthermore somewhere later on in the code I free content* as well, which is where the double free error comes from. However for some reason I am inclined to believe that the data is not actually "deleted".
Sorry if this is a lot, I have been confused by memory allocation, free, and pointers for a while and am trying to gain a deeper understanding.
When allocating memory (or resources in general), you must make sure that you have clear ownership semantics. Who owns the allocated resource and is responsible for freeing it?
For a function that allocate resources, sane semantics are that the function returns the allocated resource if successful, and unless otherwise specified, the caller owns that resource. If the function fails, the caller should not have to perform any cleanup.
Your load() function allocates a buffer. Throughout most of its function body, load() owns that buffer. Just before it returns success, it effectively transfers ownership of that buffer to the caller (via the content output argument). If load() had a failure point after allocating the buffer, then it should call free(buffer) along that failure path.
I also feel compelled to point out a few issues with your code:
BYTE* buffer = malloc(sizeof(BYTE));
You should test if malloc fails. Additionally, sizeof (BYTE) is not useful since it is, by definition, 1.
buffer = realloc(buffer, size + 1);
This is poor practice. If realloc fails, you will lose the old value of buffer and will leak memory. It's better to do:
BYTE* tmp = realloc(buffer, size + 1);
if (tmp == NULL)
{
free(buffer);
return false;
}
buffer = tmp;
Finally, growing your buffer by 1 byte every time is very inefficient. More typical practices would be to double the buffer size or to grow it by a larger amounts.
Related
Many people recommend doing the following to reallocate memory:
int *temp=realloc(previousVar,newSize);
if(temp==NULL){
printf("error\n");
exit(-1);
}
previousVar=temp;
I understand that, if no new variable was created, the previous pointer would be lost, as NULL would be assigned to it. But what's the point on having all this trouble, if the program will exit in case of failure anyways?
Here's a stack overflow, where the top answer has what I'm referring to:
Proper usage of realloc()
In the example that you provided it really does not matter if you assign the return value to a temporary or not. In the linked answer, the author frees the original buffer, but one could argue that it is not necessary since the process will exit anyway.
However, consider the following example:
typedef struct
{
int *values;
size_t capacity;
size_t size;
} MyBuffer;
bool append(MyBuffer *buffer, int value)
{
if (buffer->size == buffer->capacity)
{
// No more space, double the buffer.
size_t new_capacity = buffer->capacity * 2;
int *temp = realloc(buffer->values, new_capacity);
if (temp == NULL)
{
return false;
}
buffer->values = temp;
buffer->capacity = new_capacity;
}
buffer->values[buffer->size] = value;
buffer->size++;
return true;
}
The function append tries to add a new value to an already allocated buffer. If the buffer is not large enough, it tries to use realloc to obtain a larger buffer. If realloc fails the function returns false.
If we change the realloc call to set directly buffer->values we will leak memory in case of failure:
buffer->values = realloc(buffer->values, new_capacity);
if (buffer->values == NULL)
{
// Here the original `buffer->values` is lost and we can never access it again.
return false;
}
realloc does not free the original buffer, so in case of failure we no longer have access to it. This is a problem: in the best case scenario it is a memory leak, in the worst case we may have lost some data that we still needed (on top of the memory leak).
So this depends on how you handle realloc failures. If you log an error and exit immediately you don't need to use another variable to store the result. If you report the error up the call chain, or there is some cleanup that you want to do you have to do this. If you take the first approach you need to be careful if you refactor that piece of code to return an error instead of exiting, so there is some merit to always assigning the result to another variable.
I am trying to use realloc since i want to improve speed in my code. When a certain condition is fulfilled, I want to realloc a void double pointer to a larger size, but I get a segmentation fault. Here is the code.
if (p_bheap->currentSize == p_bheap->arraySize){
p_bheap->arraySize = p_bheap->arraySize*2 + 1;
p_bheap->pp_array = realloc(p_bheap->pp_array, p_bheap->arraySize);
}
This however results in a segmentation fault. If I however make my own reallocating function it works.
if (p_bheap->currentSize == p_bheap->arraySize){
p_bheap->pp_array = bheap_reallocate(p_bheap);
}
void** bheap_reallocate(bheap* p_bheap){
p_bheap->arraySize = p_bheap->arraySize*2 + 1;
void** pp_newArray = malloc(p_bheap->arraySize*sizeof(void*));
for (int i = 0; i < p_bheap->currentSize; i++){
pp_newArray[i] = p_bheap->pp_array[i];
}
free(p_bheap->pp_array);
return pp_newArray;
}
Is there any clear errors that can be spotted that I have failed to see? And for those wondering I am programming a binary heap.
If you have a previously allocated object, say str and want to adjust its memory to another size, use a temporary variable to prevent memory loss in the event realloc fails. Illustration:
char *str = calloc(20, 1);
if(str) // should always check return of calls to [c][m][re]alloc.
{ // at this point, str owns 20 bytes of memory. If you use str in a subsequent
// call to realloc, and the call fails, then the memory previously allocated in
// the original call to calloc() will be lost. (memory leak).
....
char *tmp = {0};//So instead, use a temporary variable to accept memory
//and provide a way to recover if allocation fails
tmp = realloc(str, 40);//newsize (40) in bytes
if(!tmp) //test reallocation
{
//reallocation failed.
//free previously allocated memory, and decide how to proceed.
//In this case, return a NULL, and let the calling function decide.
free(str);//if allocation fails, free the previous object and leave
return NULL;
}
//reallocation succeeded. Proceed normally
str = tmp;//reallocation succeeded, assign its address to str and proceed normally
You can't use the same memory space to receive the result. Try to use a temporary array or to allocate another space.
I am a newbie in C and I am trying to program a simple text editor, I have already written a 100 lines of stupid messy code, but it just worked. Until this SEGFAULT started showing up. I am going with the approach of switching terminal to canonical mode, and getting letter by letter from the user and do the necessary with each of 'em. The letters are added to a buffer, which is realloced extra 512 byte when the buffer is half filled, which I know is a stupid thing to do. But the cause of the SEGFAULT cant be determined. Help would be appreciated. Here's my code:
char* t_buf
int t_buf_len = 0;
int cur_buf_sz = 0;
void mem_mgr(char *buffer, unsigned long bytes){ //Function to allocate requested memory
if(buffer == NULL){
if((buffer = malloc(sizeof(char) * bytes)) == NULL){
printf("ERROR:Cannot get memory resources(ABORT)\n\r");
exit(1);
}
}
else{
realloc(buffer, bytes);
}
}
void getCharacter(){
if(t_buf_len >= (cur_buf_sz/2))
mem_mgr(t_buf, cur_buf_sz+=512);
strcpy(t_buf, "Yay! It works!");
printf("%s %d", t_buf, cur_buf_sz);
}
There are things you need to understand first,
The buffer pointer is a local variable inside the mem_mgr() function, it points to the same memory t_buf points initially, but once you modify it, it's no longer related to t_buf in any way.
So, when you return from mem_mgr() you lose the reference to the allocated memory and.
To fix this, you can pass a poitner to the pointer, and alter the actual pointer by dereferencing it.
The realloc() function, behaves exactly like malloc() if the first argument is NULL, if you read the documentation you would know that.
Memory allocation functions MUST be checked to ensure they returned a valid legal pointer, that's why you need a temporary poitner to store the return value of realloc(), because if it returns NULL, meaning that there was no memory to fulfill the request, you would lose reference to the original block of memory and you can't free it anymore.
You need to pass a pointer to your pointer to mem_mgr(), like this
int
mem_mgr(char **buffer, unsigned long bytes)
{
void *tmp = realloc(*buffer, bytes);
if (tmp != NULL) {
*buffer = tmp;
return 0;
}
return -1;
}
And then, to allocate memory
void
getCharacter()
{
if (t_buf_len >= (cur_buf_sz / 2)) {
if (mem_mgr(&t_buf, cur_buf_sz += 512) != -1) {
strcpy(t_buf, "Yay! It works!");
printf("%s %d", t_buf, cur_buf_sz);
}
}
}
The call to
mem_mgr(t_buf, cur_buf_sz+=512);
cannot change the actual parameter t_buf. You will either have to return the buffer from mem_mgr
t_buf = mem_mgr(t_buf, cur_buf_sz+=512);
or pass a pointer to t_buf
mem_mgr(&t_buf, cur_buf_sz+=512);
Furthermore, a call to realloc may change the address of the memory buffer, so you will have to use
char *tmpbuf = realloc(buffer, bytes);
if (!tmpbuf)
// Error handling
else
buffer = tmpbuf;
realloc(NULL, bytes); will behave like a malloc, so you don't need a separate branch here. This makes in total:
char *mem_mgr(char *buffer, unsigned long bytes){ //Function to allocate requested memory
char *tmpbuf = realloc(buffer, bytes);
if (!tmpbuf) {
// Error handling
}
return tmpbuf;
}
which somehow questions the reason of existence of the function mem_mgr.
As far of my concern if realloc fails we loose the information and realloc set the Buffer(pointer) to NULL
Consider de following program:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
char *ptr = malloc(256);
if (!ptr){
printf("Error, malloc\n");
exit(1);
}
strcpy(ptr, "Michi");
ptr = realloc (ptr, 1024 * 102400000uL); /* I ask for a big chunk here to make realloc to fail */
if (!ptr){
printf("Houston we have a Problem\n");
}
printf("PTR = %s\n", ptr);
if (ptr){
free(ptr);
ptr = NULL;
}
}
And the output of course is:
Houston we have a Problem
PTR = (null)
I just lost the information inside ptr.
Now to fix this we should use a temporary buffer(pointer) before to see if we get that chunk of memory and if we get it we can use it, if not we still have the main buffer(pointer) safe.
Now please consider the following program, where instead of calling realloc I call malloc on a temporary buffer(pointer):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
char *ptr = malloc(256);
char *tmpPTR = NULL;
if (!ptr){
printf("Error, malloc\n");
exit(1);
}
strcpy(ptr, "Michi");
tmpPTR = malloc (1024 * 102400000uL);
if (tmpPTR){
strcpy(tmpPTR, ptr);
strcat(tmpPTR, " - Aloha");
if (ptr){
free(ptr);
ptr = NULL;
}
}else{
printf("Malloc failed on tmpPTR\n\n");
}
if (ptr){
printf("PTR = %s\n", ptr);
free(ptr);
ptr = NULL;
}else if (tmpPTR){
printf("tmpPTR = %s\n", tmpPTR);
free(tmpPTR);
ptr = NULL;
}
}
And the output is:
Malloc failed on tmpPTR
PTR = Michi
Now why should I ever use realloc?
Is there any benefit of using realloc instead of malloc based on this context?
Your problem is with how you use realloc. You don't have to assign the result of realloc to the same pointer that you re-allocate. And as you point out it even poses a problem if the realloc fails. If you immediately assign the result to ptr then indeed you lose the previous buffer when something goes wrong. However, if you assign the result of realloc to tmpPTR, then ptr remains fine, even if the realloc fails. Use realloc as follows:
char * ptr = malloc(256);
if(!ptr){
return 1;
}
char * tmpPTR = realloc(ptr, 512);
if(!tmpPTR){
printf("Houston, we have a problem");
// ptr is fine
}else{
ptr = tmpPTR;
}
// ptr is realloc()ed
In the above code, tmpPTR is not a new (temporary) buffer, but just a (temporary) pointer. If the realloc is succesful it points to the same buffer (but possibly in a different location), and if it fails it is NULL. realloc doesn't always need to allocate a new buffer, but may be able to change the existing one to fit the new size. But if it fails, the original buffer will not be changed.
If you use malloc with a temporary buffer, then (for this example) you need at least 256 + 512 = 768 bytes and you always need to copy the old data. realloc may be able to re-use the old buffer so copying is not necessary and you don't use more memory than requested.
You can use your malloc approach, but realloc is almost always more efficient.
The realloc scheme is simple. You do not need a separate call to malloc. For example if you initially have 256 bytes allocated for ptr, simply use a counter (or index, i below) to keep track of how much of the memory within the block allocated to ptr has been used, and when the counter reaches the limit (1 less than the max for 0-based indexes, or 2 less than the max if you are using ptr as a string), realloc.
Below shows a scheme where you are simply adding 256 additional bytes to ptr each time the allocation limit is reached:
int i = 0, max = 256;
char *ptr = malloc(max);
/* do whatever until i reaches 255 */
if (i + 1 >= max) {
void *tmp = realloc (ptr, max + 256);
if (!tmp) {
fprintf (stderr, "error: realloc - memory exhausted.\n")
/* handle error */
}
ptr = tmp;
max += 256;
}
note: your handle error can exit whatever loop you are in to preserve the existing data in ptr. You do not need to exit at that point.
The advantage of realloc over malloc is that it may be able to extend the original dynamic memory area so without the need to copy all the previous elements; you can't do that with malloc1. And whether this optimization is available costs no work to you.
Let's assume you have a previously allocated pointer:
char *some_string = malloc(size); // assume non-NULL
Then
if (realloc_needed) {
char *tmp = realloc(some_string, new_size);
if ( tmp == NULL )
// handle error
else
some_string = tmp; // (1)
At (1), you update the old pointer with the new one. Two things can happen: the address has effectively changed (and the elements been automatically copied) or it hasn't - you don't really care. Either way, your data is now at some_string.
Only the actual implementation (OS / libc) knows whether it's possible to enlarge the block: you don't get to see it, it's an implementation detail. You can however check your implementation's code and see how it's implemented.
Now to fix this we should use a temporary buffer(pointer) before to see if we get that chunk of memory and if we get it we can use it, if not we still have the main buffer(pointer) safe.
That not only doesn't help, it makes things worse because now you no longer have the pointer to the block you tried to reallocate. So how can you free it?
So it:
Wastes memory.
Require an extra allocate, copy, and free.
Makes the realloc more likely to fail because of 1.
Leaks memory since the pointer to the block you tried to reallocate is lost.
So no, that's not a good way to handle realloc returning NULL. Save the original pointer when you call realloc so you can handle failure sanely. The point of realloc to save you from having to manage two copies of the data and to avoid even making them when that's possible. So let realloc do this work for you whenever you can.
It is technically malloc(size) that is unneeded, because realloc(NULL, size) performs the exact same task.
I often read inputs of indeterminate length. As in the following function example, I rarely use malloc(), and instead use realloc() extensively:
#include <stdlib.h>
#include <errno.h>
struct record {
/* fields in each record */
};
struct table {
size_t size; /* Number of records allocated */
size_t used; /* Number of records in table */
struct record item[]; /* C99 flexible array member */
};
#define MAX_ITEMS_PER_READ 1
struct table *read_table(FILE *source)
{
struct table *result = NULL, *temp;
size_t size = 0;
size_t used = 0, n;
int err = 0;
/* Read loop */
while (1) {
if (used + MAX_ITEMS_PER_READ > size) {
/* Array size growth policy.
* Some suggest doubling the size,
* or using a constant factor.
* Here, the minimum is
* size = used + MAX_ITEMS_PER_READ;
*/
const size_t newsize = 2*MAX_ITEMS_PER_READ + used + used / 2;
temp = realloc(result, sizeof (struct table) +
newsize * sizeof (result->item[0]));
if (!temp) {
err = ENOMEM;
break;
}
result = temp;
size = newsize;
}
/* Read a record to result->item[used],
* or up to (size-used) records starting at result->item + used.
* If there are no more records, break.
* If an error occurs, set err = errno, and break.
*
* Increment used by the number of records read: */
used++;
}
if (err) {
free(result); /* NOTE: free(NULL) is safe. */
errno = err;
return NULL;
}
if (!used) {
free(result);
errno = ENODATA; /* POSIX.1 error code, not C89/C99/C11 */
return NULL;
}
/* Optional: optimize table size. */
if (used < size) {
/* We don't mind even if realloc were to fail here. */
temp = realloc(result, sizeof (struct table) +
used * sizeof table->item[0]);
if (temp) {
result = temp;
size = used;
}
}
result->size = size;
result->used = used;
errno = 0; /* Not normally zeroed; just my style. */
return result;
}
My own practical reallocation policies tend to be very conservative, limiting the size increase to a megabyte or so. There is a very practical reason for this.
On most 32-bit systems, userspace applications are limited to 2 to 4 gigabyte virtual address space. I wrote and ran simulation systems on a lot of different x86 systems (32-bit), all with 2 to 4 GB of memory. Usually, most of that memory is needed for a single dataset, which is read from disk, and manipulated in place. When the data is not in final form, it cannot be directly memory-mapped from disk, as a translation -- usually from text to binary -- is needed.
When you use realloc() to grow the dynamically allocated array to store such huge (on 32-bit) datasets, you are only limited by the available virtual address space (assuming there is enough memory available). (This especially applies to 32-bit applications on 64-bit systems.)
If, instead, you use malloc() -- i.e., when you notice your dynamically allocated array is not large enough, you malloc() a new one, copy the data over, and discard the old one --, your final data set size is limited to a lesser size, the difference depending on your exact array size growth policy. If you use the typical double when resizing policy, your final dataset is limited to about half (the available virtual address space, or available memory, whichever is smaller).
On 64-bit systems with lots and lots of memory, realloc() still matters, but is much more of a performance issue, rather than on 32-bit, where malloc() is a limiting factor. You see, when you use malloc() to allocate a completely new array, and copy the old data to the new array, the resident set size -- the actual amount of physical RAM needed by your application -- is larger; you use 50% more physical RAM to read the data than you would when using realloc(). You also do a lot of large memory-to-memory copies (when reading a huge dataset), which are limited to physical RAM bandwidth, and indeed slow down your application (although, if you are reading from a spinning disk, that is the actual bottleneck anyway, so it won't matter much).
The nastiest effect, and the most difficult to benchmark, are the indirect effects. Most operating systems use "free" RAM to cache recently accessed files not modified yet, and this really does decrease the wall clock time used by most workloads. (In particular, caching typical libraries and executables may shave off seconds from the startup time of large application suites, if the storage media is slow (ie. a spinning disk, and not a SSD).) Your memory-wasting malloc()-only approach gobbles up much more actual physical RAM than needed, which evicts cached, often useful, files from memory!
You might benchmark your program, and note that there is no real difference in run times between using your malloc()-only approach and realloc() approach I've shown above. But, if it works with large datasets, the users will notice that using the malloc()-only program slows down other programs much more than the realloc()-using program, with the same data!
So, although on 64-bit systems with lots of RAM using malloc() only is basically an inefficient way to approach things, on 32-bit systems it limits the size of dynamically allocated arrays when the final size is unknown beforehand. Only using realloc() can you there achieve the maximum possible dataset size.
Your assumption is wrong. Please do note that a pointer is not a buffer. When the function realloc() succeeds, it deallocates the old pointer(frees the original buffer) and return a new pointer to the new allocation(buffer), but when it fails, it leaves the old buffer intact and returns NULL.
So, you do not need a temporary buffer. You need a temporary pointer. I am going to borrow the example from kninnug, this is what you need to do:
char * ptr = malloc(256);
if (!ptr) {
return 1;
}
char * tmpPTR = realloc(ptr, 512);
if (!tmpPTR) {
printf("Houston, we have a problem");
// ptr is fine
}
else {
ptr = tmpPTR;
}
// ptr is realloc()ed
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int x;
int *in, *begin;
in = (int *)malloc(sizeof(int));
begin = in;
while ((x = getchar()) != EOF) {
*in = x;
in++;
in = (int *)malloc(sizeof(int));
}
*in = EOF;
while ((x = *begin) != EOF) {
putchar(x);
begin++;
}
free(in);
return 0;
}
I have a sneaking suspicion that it does.
With this program, I'm trying to store user input of an indefinite size into memory using pointers, as opposed to using char string[255]; fgets(string, sizeof(string)); etc.
EDIT: The program doesn't crash or anything when I run it, I just have a feeling there's memory getting allocated that isn't getting freed.
Yes, the program has a memory leak.
int *in, *begin;
in = (int *)malloc(sizeof(int)); /* allocate space for 1 int, at location "X" */
begin = in;
while ((x = getchar()) != EOF) {
*in = x;
in++; /* "in" increments address (to location) "X+1" */
in = (int *)malloc(sizeof(int)); /* address "X+1" is lost as malloc returns
a different memory location, *not*
necessarily at "X+2". Access to
previous data other than pointed to by
"begin" is lost */
}
*in = '\0'; /* this makes probably more senese than assigining EOF here */
There needs to be corresponding calls to free() when you allocate memory.
Also, I don't think the input is stored correctly.
in is never given a continious block of memory to store the data. Instead a single memory location of size to store an int is repeatedly allocated and assigned to in, but we don't really know where this memory is, so all of these allocations are lost since only a single pointer in is keeping track of them.
In other words, the leak consists of repeatedly allocating memory for the size of an int, assigning it to in, and then losing any reference to that location next time through the loop.
Variable begin initially points at the first item entered, but then subsequently trapses through unknown memory as its pointer value is incremented by 1 repeatedly in the output loop.
A better approach would be to allocate a single, larger continuous buffer once at the start and then use it as you increment your in pointer, or to start with a smaller amount but then monitor memory use and realloc() more as needed (but much more overhead to save a few byes of memory).
Also, at the end of your first loop rather than assigning EOF to in, it would make more sense to put in a null character.
Finally, the free(in) call at the bottom of the program frees only a single memory location, none of the other previously allocated memory.
Here's a quickly put together version that works, I tried to make minimal changes to the original code and to keep your code structure intact (I am sure you had your reasons for writing it this way with two loops in the first place) though this could be written much more compactly with just one loop.
Note I initially allocate space for 100 characters, adjust this according to your needs, or alternatively allocate less initially, but then keep track of memory consumption and realloc() more memory as you need (which I think was your initial intention, but just not implemented quite correctly).
int main(void) {
int x;
int *in, *begin;
int *start_loc;
in = (int *)malloc(sizeof(int) * 100); /* continious space */
begin = in;
start_loc = in; /* keep track of start location for final free() call */
while ((x = getchar()) != EOF) {
*in = x;
in++;
}
*in = 0; /* terminator for the input string/data */
while (*begin != 0) { /* simplified */
putchar(*begin);
begin++;
}
free(start_loc); /* free allocated memory */
return 0;
}
This could be written without the use of a new variable start_loc (by reusing in for instance) but I chose to write it this way to emphasize the importance of keeping track of the start of your memory allocation and the ability to correctly free memory allocated, so to address your memory leak problem.
Yes you have. Free will deallocate memory for one only integer. You have to call free for every malloc call you have done.
Also to store the characters in a continuous buffer you have to malloc an amount of memory at the beginning and use realloc if the characters you read become more than those initially allocated memory for.
Also don't forget to allocate one more character for the \0 at the end of the string.
When you are done you can call free(buffer) and... Success! No memory leaks!
And the code for it:
/* Start with an initial size */
int size = 128;
char *buffer = (char *)malloc(size + 1);
int i = 0;
while ((x = getchar()) != EOF) {
buffer[i] = x;
i++;
if(i == size){
/*Do realloc and increase size */
}
}
buffer[i] = '\0';
/* Do what you want with buffer */
free(buffer);
Of course there is a memory leak, for every call to malloc there sould be a corresponding call to free in your program.
In your program malloc is called several times but there is only one call to free.
Levon's answer is correct. You increase the value of in here:
in++;
...but then you reassign it to an address that is arbitrary here:
in = (int *)malloc(sizeof(int));
To achieve what you're trying to do you either need to:
Allocate a large chunk of contiguous memory in one go, and realloc() whenever it needs to expand (this is what you're trying to achieve), or;
Use linked lists to navigate through a list of non-contiguous memory addresses (this is what you've actually managed to write).
When you use malloc to allocate memory, you should make sure that the pointer which point to the memory is not NULL, and after you free the memory, you are better to set the pointer to NULL