From 73ef2e2ec50503889bda1ae93ca28475045be3d5 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 5 Apr 2016 22:08:55 +0300 Subject: [PATCH] Fix GC_REALLOC to call GC_FREE if new size is zero and pointer is non-NULL * dbg_mlc.c (GC_debug_realloc): Call GC_debug_free (and return NULL) if lb is zero and p is non-NULL. * extra/AmigaOS.c (GC_amiga_realloc): Do not retry and do not call WARN if new_size_in_bytes is zero. * include/gc.h (GC_realloc): Refine comment (better document the cases of NULL and/or zero arguments). * mallocx.c (GC_realloc): Call GC_free (skip it if IGNORE_FREE) and return NULL if lb is zero and p is non-NULL. --- dbg_mlc.c | 5 +++++ extra/AmigaOS.c | 5 +++-- include/gc.h | 15 ++++++++++++++- mallocx.c | 6 ++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/dbg_mlc.c b/dbg_mlc.c index f805473f..d334874e 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -877,6 +877,11 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) if (p == 0) { return GC_debug_malloc(lb, OPT_RA s, i); } + if (0 == lb) /* and p != NULL */ { + GC_debug_free(p); + return NULL; + } + # ifdef GC_ADD_CALLER if (s == NULL) { GC_caller_func_offset(ra, &s, &i); diff --git a/extra/AmigaOS.c b/extra/AmigaOS.c index 8f99b746..3e7b3a0a 100644 --- a/extra/AmigaOS.c +++ b/extra/AmigaOS.c @@ -581,7 +581,8 @@ void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){ void *ret; latestsize=new_size_in_bytes; ret=GC_realloc(old_object,new_size_in_bytes); - if(ret==NULL && GC_AMIGA_MEMF==(MEMF_FAST | MEMF_CLEAR)){ + if(ret==NULL && new_size_in_bytes != 0 + && GC_AMIGA_MEMF==(MEMF_FAST | MEMF_CLEAR)){ /* Out of fast-mem. */ #ifdef GC_AMIGA_GC if(!GC_dont_gc){ @@ -606,7 +607,7 @@ void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){ } #endif } - if(ret==NULL){ + if(ret==NULL && new_size_in_bytes != 0){ WARN("Out of Memory! Returning NIL!\n", 0); } #ifdef GC_AMIGA_PRINTSTATS diff --git a/include/gc.h b/include/gc.h index f08a0b40..98186726 100644 --- a/include/gc.h +++ b/include/gc.h @@ -481,7 +481,20 @@ GC_API size_t GC_CALL GC_size(const void * /* obj_addr */) GC_ATTR_NONNULL(1); /* The resulting object has the same kind as the original. */ /* If the argument is stubborn, the result will have changes enabled. */ /* It is an error to have changes enabled for the original object. */ -/* Follows ANSI conventions for NULL old_object. */ +/* It does not change the content of the object from its beginning to */ +/* the minimum of old size and new_size_in_bytes; the content above in */ +/* case of object size growth is initialized to zero (not guaranteed */ +/* for atomic object type). The function follows ANSI conventions for */ +/* NULL old_object (i.e., equivalent to GC_malloc regardless of new */ +/* size). If new size is zero (and old_object is non-NULL) then the */ +/* call is equivalent to GC_free (and NULL is returned). If old_object */ +/* is non-NULL, it must have been returned by an earlier call to */ +/* GC_malloc* or GC_realloc. In case of the allocation failure, the */ +/* memory pointed by old_object is untouched (and not freed). */ +/* If the returned pointer is not the same as old_object and both of */ +/* them are non-NULL then old_object is freed. Returns either NULL (in */ +/* case of the allocation failure or zero new size) or pointer to the */ +/* allocated memory. */ GC_API void * GC_CALL GC_realloc(void * /* old_object */, size_t /* new_size_in_bytes */) /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2); diff --git a/mallocx.c b/mallocx.c index 80118e72..a526d9e3 100644 --- a/mallocx.c +++ b/mallocx.c @@ -83,6 +83,12 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb) int obj_kind; if (p == 0) return(GC_malloc(lb)); /* Required by ANSI */ + if (0 == lb) /* and p != NULL */ { +# ifndef IGNORE_FREE + GC_free(p); +# endif + return NULL; + } h = HBLKPTR(p); hhdr = HDR(h); sz = hhdr -> hb_sz; -- 2.40.0