In this article I will present to you a safe wrapper for freeing memory allocated with *alloc family functions. The standard function “void free (void * pointer)” from stdlib library does not check the given pointer to see whether it is NULL and does not NULL terminate the pointer before it returns either. So, setting a pointer to NULL after freeing is considered a good practice, and can reduce the chances of unpredictable behavior if the memory is later accessed; segmentation faults when the memory is no longer accessible and potential security risks.
Here, follows the header of the source code unit of the wrapper:
/* * Copyright (C) 2014 Efstathios Chatzikyriakidis (stathis.chatzikyriakidis@gmail.com). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _MEMORY_MANAGEMENT_HELPER_H_ #define _MEMORY_MANAGEMENT_HELPER_H_ /* * function prototypes. */ void safe_memory_free (void ** pointer_address); #endif // _MEMORY_MANAGEMENT_HELPER_H_
Next, follows the implementation of the source code unit of the wrapper:
/* * Copyright (C) 2014 Efstathios Chatzikyriakidis (stathis.chatzikyriakidis@gmail.com). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stdlib.h> #include "memory-management-helper.h" /* * functions. */ void safe_memory_free (void ** pointer_address) { if (pointer_address != NULL && *pointer_address != NULL) { free (*pointer_address); *pointer_address = NULL; } }
If the address of the pointer is not NULL and the address the pointer points to is also not NULL then the memory is freed and the pointer is set to NULL. So, any other consecutive calls will be ignored. In order not to pass always the address of the pointer when calling the safe_memory_free function you can use the following macro definition which does it automatically whenever is called:
/* * Copyright (C) 2014 Efstathios Chatzikyriakidis (stathis.chatzikyriakidis@gmail.com). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _MEMORY_MANAGEMENT_HELPER_MACROS_H_ #define _MEMORY_MANAGEMENT_HELPER_MACROS_H_ #include "memory-management-helper.h" /* * macros. */ #define safe_free(pointer) safe_memory_free((void **) &(pointer)) #endif // _MEMORY_MANAGEMENT_HELPER_MACROS_H_
So, here is an example of using the helper wrapper through the macro definition to clear an HTTP request:
void clear_http_request (http_request_t * http_request) { if (http_request) { safe_free(http_request->method); safe_free(http_request->uri); safe_free(http_request->query); safe_free(http_request->protocol_version); while (http_request->headers) { http_header_field_t * http_header_field = http_request->headers; safe_free(http_header_field->name); safe_free(http_header_field->value); http_request->headers = http_header_field->next; safe_free(http_header_field); } safe_free(http_request); } }
Happy Hacking!