Merge #13 Add some tips to C-Allocators

This commit is contained in:
Huzaifa Sidhpurwala 2020-10-13 10:16:59 +00:00
commit 0888d3db13

View file

@ -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 pointer will always return false, so it is impossible to detect
movement this way. 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 ==== Handling Memory Allocation Errors
Recovering from out-of-memory errors is often difficult or even 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, function, check if `malloc` had been called,
and free the buffer as needed. 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]] [[sect-Defensive_Coding-C-Allocators-Arrays]]
=== Array Allocation === Array Allocation
@ -118,6 +156,12 @@ to allocate an array of `n` elements of type
greater than `((size_t) -1) / sizeof(T)`. See greater than `((size_t) -1) / sizeof(T)`. See
<<sect-Defensive_Coding-C-Arithmetic>>. <<sect-Defensive_Coding-C-Arithmetic>>.
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]] [[sect-Defensive_Coding-C-Allocators-Custom]]
=== Custom Memory Allocators === Custom Memory Allocators