From 8b7c607f1b09c64071dd64650c408067aebb7ad0 Mon Sep 17 00:00:00 2001 From: Riccardo Schirone Date: Mon, 31 Jan 2022 11:42:24 +0000 Subject: [PATCH] Update modules/ROOT/pages/programming-languages/C.adoc Reserve a special section for memory leaks and automatic memory management. --- .../ROOT/pages/programming-languages/C.adoc | 58 +++++++++++-------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/modules/ROOT/pages/programming-languages/C.adoc b/modules/ROOT/pages/programming-languages/C.adoc index 50d6d26..ce92257 100644 --- a/modules/ROOT/pages/programming-languages/C.adoc +++ b/modules/ROOT/pages/programming-languages/C.adoc @@ -551,6 +551,38 @@ free the old pointer. Therefore, the idiom `ptr = realloc(ptr, size);` is wrong because the memory pointed to by `ptr` leaks in case of an error. +==== Memory leaks +After a memory area has been allocated with functions like `malloc`, +`calloc`, etc. and it is no longer necessary, it must be freed in +order for the system to release the memory region and re-use it if +necessary. Failing to do so may lead to the application using more +memory than necessary and, in some cases, crashing due to no more +memory being available. + +If portability is not important in your program, an alternative way of +automatic memory management is to leverage the `cleanup` attribute +supported by the recent versions of GCC and Clang. If a local variable +is declared with the attribute, the specified cleanup function will be +called when the variable goes out of scope. + +[source,c] +---- +static inline void freep(void *p) { + free(*(void**) p); +} + +void somefunction(const char *param) { + if (strcmp(param, "do_something_complex") == 0) { + __attribute__((cleanup(freep))) char *ptr = NULL; + + /* Allocate a temporary buffer */ + ptr = malloc(size); + + /* Do something on it, but do not need to manually call free() */ + } +} +---- + [[sect-Defensive_Coding-C-Use-After-Free]] ==== Use-after-free errors @@ -632,7 +664,7 @@ started as a GNU extension. For large objects exceeding the page size, there is no error checking, either. In both cases, negative or very large sizes can trigger a -stack-pointer wraparound, and the stack pointer and end up +stack-pointer wraparound, and the stack pointer ends up pointing into caller stack frames, which is fatal and can be exploitable. @@ -644,30 +676,6 @@ Otherwise, call `malloc`. When exiting the function, check if `malloc` had been called, and free the buffer as needed. -If portability is not important in your program, an alternative way of -automatic memory management is to leverage the `cleanup` attribute -supported by the recent versions of GCC and Clang. If a local variable -is declared with the attribute, the specified cleanup function will be -called when the variable goes out of scope. - -[source,c] ----- -static inline void freep(void *p) { - free(*(void**) p); -} - -void somefunction(const char *param) { - if (strcmp(param, "do_something_complex") == 0) { - __attribute__((cleanup(freep))) char *ptr = NULL; - - /* Allocate a temporary buffer */ - ptr = malloc(size); - - /* Do something on it, but do not need to manually call free() */ - } -} ----- - [[sect-Defensive_Coding-C-Allocators-Arrays]] === Array Allocation