mirror of
http://git.haproxy.org/git/haproxy.git
synced 2026-02-16 06:22:05 +02:00
CLEANUP: tree-wide: replace free(x);x=NULL with ha_free(&x)
This makes the code more readable and less prone to copy-paste errors.
In addition, it allows to place some __builtin_constant_p() predicates
to trigger a link-time error in case the compiler knows that the freed
area is constant. It will also produce compile-time error if trying to
free something that is not a regular pointer (e.g. a function).
The DEBUG_MEM_STATS macro now also defines an instance for ha_free()
so that all these calls can be checked.
178 occurrences were converted. The vast majority of them were handled
by the following Coccinelle script, some slightly refined to better deal
with "&*x" or with long lines:
@ rule @
expression E;
@@
- free(E);
- E = NULL;
+ ha_free(&E);
It was verified that the resulting code is the same, more or less a
handful of cases where the compiler optimized slightly differently
the temporary variable that holds the copy of the pointer.
A non-negligible amount of {free(str);str=NULL;str_len=0;} are still
present in the config part (mostly header names in proxies). These
ones should also be cleaned for the same reasons, and probably be
turned into ist strings.
This commit is contained in:
@@ -73,6 +73,17 @@
|
||||
#define BUG_ON(cond)
|
||||
#endif
|
||||
|
||||
/* more reliable free() that clears the pointer */
|
||||
#define ha_free(x) do { \
|
||||
typeof(x) __x = (x); \
|
||||
if (__builtin_constant_p((x)) || __builtin_constant_p(*(x))) { \
|
||||
/* provoke a build-time error */ \
|
||||
extern volatile int call_to_ha_free_attempts_to_free_a_constant; \
|
||||
call_to_ha_free_attempts_to_free_a_constant = 1; \
|
||||
} \
|
||||
free(*__x); \
|
||||
*__x = NULL; \
|
||||
} while (0)
|
||||
|
||||
#if defined(DEBUG_MEM_STATS)
|
||||
#include <stdlib.h>
|
||||
@@ -129,6 +140,26 @@ struct mem_stats {
|
||||
free(__x); \
|
||||
})
|
||||
|
||||
#undef ha_free
|
||||
#define ha_free(x) ({ \
|
||||
typeof(x) __x = (x); \
|
||||
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
|
||||
.file = __FILE__, .line = __LINE__, \
|
||||
.type = MEM_STATS_TYPE_FREE, \
|
||||
}; \
|
||||
__asm__(".globl __start_mem_stats"); \
|
||||
__asm__(".globl __stop_mem_stats"); \
|
||||
if (__builtin_constant_p((x)) || __builtin_constant_p(*(x))) { \
|
||||
/* provoke a build-time error */ \
|
||||
extern volatile int call_to_ha_free_attempts_to_free_a_constant; \
|
||||
call_to_ha_free_attempts_to_free_a_constant = 1; \
|
||||
} \
|
||||
if (*__x) \
|
||||
_HA_ATOMIC_ADD(&_.calls, 1); \
|
||||
free(*__x); \
|
||||
*__x = NULL; \
|
||||
})
|
||||
|
||||
#undef malloc
|
||||
#define malloc(x) ({ \
|
||||
size_t __x = (x); \
|
||||
|
||||
Reference in New Issue
Block a user