diff options
author | H. Peter Anvin <hpa@zytor.com> | 2017-01-24 14:04:44 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2017-01-24 14:04:44 -0800 |
commit | a92a7dce5ed61d482c549abc3c1ef144025ec2ae (patch) | |
tree | bbfbb2523c6a3f3683a2ab451092c85928298f2e | |
parent | 75f2c1e131a7651a793abc8f59aea09b6226ce7d (diff) | |
download | nasm-a92a7dce5ed61d482c549abc3c1ef144025ec2ae.tar.gz |
nasm_delete(): ugly hack to make it side-effect-free
Use an ugly hack to make nasm_delete() side effect free. This assumes
all pointers have the same internal NULL pointer representation as
void *, however, we already assume zero-initialized memory will
represent a NULL pointer, so hopefully this is okay on any platform we
actually care about.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | include/nasmlib.h | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/include/nasmlib.h b/include/nasmlib.h index 218cf636..60c16df3 100644 --- a/include/nasmlib.h +++ b/include/nasmlib.h @@ -153,13 +153,24 @@ void nasm_free(void *); char * safe_alloc nasm_strdup(const char *); char * safe_alloc nasm_strndup(const char *, size_t); +/* Assert the argument is a pointer without evaluating it */ +#define nasm_assert_pointer(p) ((void)sizeof(*(p))) + #define nasm_new(p) ((p) = nasm_zalloc(sizeof(*(p)))) #define nasm_newn(p,n) ((p) = nasm_calloc(sizeof(*(p)),(n))) /* - * Careful: nasm_delete() is not side-effect safe. - * Any ideas how to fix that? + * This is broken on platforms where there are pointers which don't + * match void * in their internal layout. It unfortunately also + * loses any "const" part of the argument, although hopefully the + * compiler will warn in that case. */ -#define nasm_delete(p) do { nasm_free(p); (p) = NULL; } while (0) +#define nasm_delete(p) \ + do { \ + void **_pp = (void **)&(p); \ + nasm_assert_pointer(p); \ + nasm_free(*_pp); \ + *_pp = NULL; \ + } while (0) #define nasm_zero(p) (memset((p), 0, sizeof(*(p)))) /* |