Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Mar 2005 13:06:52 +0300 (MSK)
From:      Dmitrij Tejblum <tejblum@yandex-team.ru>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/79048: realloc() copies data even when the size of allocated memory decrease
Message-ID:  <200503201006.j2KA6q4b047338@developer.yandex.ru>
Resent-Message-ID: <200503201010.j2KAA9s9095325@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         79048
>Category:       bin
>Synopsis:       realloc() copies data even when the size of allocated memory decrease
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Mar 20 10:10:07 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Dmitrij Tejblum
>Release:        FreeBSD 5.4-PRERELEASE i386
>Organization:
>Environment:

>Description:

If a program malloc() a large piece of memory (e.g. p = malloc(1024000)) and
then realloc() it to a smaller size (e.g. realloc(p, 512000)) realloc() 
allocate new piece of memory and copy the old piece to new one. The unnecessary
reallocation also sometimes lead to allocation failures. But it is easy to
mark the tail of old memory as free.

>How-To-Repeat:

>Fix:

--- malloc.c	Sun Mar 20 03:11:19 2005
+++ malloc.c	Sun Mar 20 03:13:15 2005
@@ -286,6 +286,7 @@ static int extend_pgdir(u_long index);
 static void *imalloc(size_t size);
 static void ifree(void *ptr);
 static void *irealloc(void *ptr, size_t size);
+static __inline void free_pages(void *ptr, u_long index, struct pginfo const *info);
 
 static void
 wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
@@ -787,10 +788,15 @@ irealloc(void *ptr, size_t size)
 
         if (!malloc_realloc && 			/* Unless we have to, */
 	  size <= osize && 			/* .. or are too small, */
-	  size > (osize - malloc_pagesize)) {	/* .. or can free a page, */
+	  size > malloc_maxsize) {		/* .. or want to allocate a chunk */
 	    if (malloc_junk)
 		memset((u_char *)ptr + size, SOME_JUNK, osize-size);
-	    return (ptr);			/* ..don't do anything else. */
+	    if (size <= (osize - malloc_pagesize)) {    /* have something to free */
+		size_t nsize = pageround(size);
+		void *fptr = (u_char *)ptr + nsize;
+		free_pages(fptr, ptr2index(fptr), MALLOC_FIRST);
+	    }
+	    return (ptr);
 	}
 
     } else if (*mp >= MALLOC_MAGIC) {		/* Chunk allocation */


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200503201006.j2KA6q4b047338>