From e6baf3d2fb33ff980611fcfd166842489615c8d4 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 12 Oct 2020 10:10:07 +0200 Subject: [PATCH 1/3] C-Allocators: Mention `reallocarray` for safe array allocation Signed-off-by: Daiki Ueno --- modules/ROOT/pages/programming-languages/C-Allocators.adoc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/ROOT/pages/programming-languages/C-Allocators.adoc b/modules/ROOT/pages/programming-languages/C-Allocators.adoc index 1ef22cd..6bb137a 100644 --- a/modules/ROOT/pages/programming-languages/C-Allocators.adoc +++ b/modules/ROOT/pages/programming-languages/C-Allocators.adoc @@ -118,6 +118,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 From c253c7d93ea65646a1d674fee9633174a3be734b Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 12 Oct 2020 10:21:28 +0200 Subject: [PATCH 2/3] C-Allocators: Mention `cleanup` attribute Signed-off-by: Daiki Ueno --- .../programming-languages/C-Allocators.adoc | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/modules/ROOT/pages/programming-languages/C-Allocators.adoc b/modules/ROOT/pages/programming-languages/C-Allocators.adoc index 6bb137a..8c858f6 100644 --- a/modules/ROOT/pages/programming-languages/C-Allocators.adoc +++ b/modules/ROOT/pages/programming-languages/C-Allocators.adoc @@ -105,6 +105,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 From 3a1876bdafb153924c2062a49251d7ccfcea4541 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 12 Oct 2020 10:35:07 +0200 Subject: [PATCH 3/3] C-Allocators: Mention `realloc` behavior if size is zero Signed-off-by: Daiki Ueno --- .../pages/programming-languages/C-Allocators.adoc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/ROOT/pages/programming-languages/C-Allocators.adoc b/modules/ROOT/pages/programming-languages/C-Allocators.adoc index 8c858f6..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