Friday 7 June 2019

c - Allocating memory and freeing them. Should we set them to NULL?



gcc (GCC) 4.7.0
c89


Hello,



I am wondering if I am thinking correctly here. When I allocate memory using malloc. malloc will return a pointer to a size in memory.




So before I allocate my memory all pointers will have the value NULL.



Using this code snippet:



struct address *db_row = NULL;

db_row = malloc(sizeof(struct address));
db_row->name = malloc(sizeof(char) * 10);
db_row->email = malloc(sizeof(char) *10);


free(db_row->name);
free(db_row->email);
free(db_row);


I have done this in the gdb debugger for db_row before allocating memory:



(gdb) p db_row
$20 = (struct address *) 0x0
(gdb) p *db_row

Cannot access memory at address 0x0


Which is correct, as no memory address has been allocated.
After I allocate memory I get the following when I do the same:



(gdb) p db_row
$25 = (struct address *) 0x602310
(gdb) p *db_row
$26 = {id = 0, set = 0, name = 0x0, email = 0x0}



However, after I have free the memory I still get the same memory address, should it not be NULL as in the first case before allocating any memory?



After freeing the memory:



(gdb) p db_row
$28 = (struct address *) 0x602310
(gdb) p *db_row
$27 = {id = 6300480, set = 0, name = 0x602330 "", email = 0x602350 " #`"}



As you can see its still pointing to the same memory location, is this correct?



Finally, I added this at the end to see if I could do a double free:



if(db_row != NULL) {
free(db_row);
}


if(db_row != NULL) {
free(db_row);
}


I get a stack dump on the second call to free. But as a safety measure should you always check to make sure you are not trying to do a double free?



It it worth setting the pointers to NULL after free them?



db_row = NULL;



Many thanks for any suggestions,


Answer




But as a safety measure should you always check to make sure you are not trying to free a NULL pointer?




Calling free() with a NULL pointer is safe and nothing occurs. Calling free() does not NULL the pointer, you may do this explicitly. NULLing a pointer after calling free() would prevent the double free on the same pointer variable:




/* Assuming 'db_row' is referring to a valid address
at this stage the following code will not result
in a double free.*/
free(db_row);
db_row = NULL;
free(db_row);


If another pointer variable is pointing to the same address and is passed to free() then a double free still occurs.




Just because a pointer is not-NULL does not guarantee that it points to a valid address. It is the programmer's responsibility to ensure double free()s do not occur. NULLing pointer variables after a call to free() helps but does not provide a guarantee as multiple pointer variables can be pointing at the same address.







But as a safety measure should you always check to make sure you are not trying to do a double free?




There is no way to query a pointer variable to determine if the memory at the address that it holds has already been free()d. A pointer variable holds an address, nothing more.


No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...