From: Ivan Maidanski Date: Tue, 5 Apr 2016 19:08:55 +0000 (+0300) Subject: Fix GC_REALLOC to call GC_FREE if new size is zero and pointer is non-NULL X-Git-Tag: gc7_6_0~42 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b929f72e3d08a1c020e3b6ea0890ca8ac34eb50d;p=gc 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. --- diff --git a/dbg_mlc.c b/dbg_mlc.c index 97b5636e..37c8f426 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -894,6 +894,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 2ec11337..c22bc662 100644 --- a/extra/AmigaOS.c +++ b/extra/AmigaOS.c @@ -508,7 +508,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){ @@ -533,7 +534,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 3effc03f..af27bc57 100644 --- a/include/gc.h +++ b/include/gc.h @@ -526,7 +526,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 38fe3c47..22c93b1c 100644 --- a/mallocx.c +++ b/mallocx.c @@ -92,6 +92,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;