diff --git a/modules/ROOT/pages/programming-languages/C-Allocators.adoc b/modules/ROOT/pages/programming-languages/C-Allocators.adoc index 1ef22cd..3a15fa2 100644 --- a/modules/ROOT/pages/programming-languages/C-Allocators.adoc +++ b/modules/ROOT/pages/programming-languages/C-Allocators.adoc @@ -43,6 +43,20 @@ compiler may assume that a comparison between the old and new pointer will always return false, so it is impossible to detect movement this way. +On a related note, `realloc` frees the memory area if the new size is +zero. If the size unintentionally becomes zero, as a result of +unsigned integer wrap-around for instance, the following idiom causes +a double-free. + +[source,c] +---- +new_size = size + x; /* 'x' is a very large value and the result wraps around to zero */ +new_ptr = realloc(ptr, new_size); +if (!new_ptr) { + free(ptr); +} +---- + ==== Handling Memory Allocation Errors Recovering from out-of-memory errors is often difficult or even @@ -105,6 +119,30 @@ 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 @@ -118,6 +156,12 @@ to allocate an array of `n` elements of type greater than `((size_t) -1) / sizeof(T)`. See <>. +GNU libc provides a dedicated function `reallocarray` that allocates +an array with those checks performed internally. However, care must +be taken if portability is important: while the interface originated +in OpenBSD and has been adopted in many other platforms, NetBSD +exposes an incompatible behavior with the same interface. + [[sect-Defensive_Coding-C-Allocators-Custom]] === Custom Memory Allocators