www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/08/22/07:28:43

Date: Sun, 22 Aug 1999 13:14:11 +0300 (IDT)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
X-Sender: eliz AT is
To: DJ Delorie <dj AT delorie DOT com>
cc: djgpp-workers AT delorie DOT com
Subject: Possible Bug in realloc() (fwd)
Message-ID: <Pine.SUN.3.91.990822131235.6405Z-100000@is>
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com

The original message (from c.o.m.d.) is attached in its entirety below.

>    Let's say you have 600 total units of space on the computer.
>    Say 300 units are allocated in 1 large block and the subsequent 300 are
> free.
>    If you want to enlarge the first block to 500 units, a "smart" realloc()
> could just enlarge the 300 unit block to 500 units if no block were already
> using the 200 units of space immediately following the 300 unit block.
> Malloc(), on the other hand would only see 300 free units(not knowing the
> 300 units already used could be part of the necessary 500) and so would deny
> the request for a 500 unit block whereas a "smart" reallloc could grant it.

It seems that the real benefit from such an optimization in `realloc'
would be to avoid the run-time penalty of copying the data from the
old buffer to the new one.  This penalty might be substantial if the
buffer is large.

Looking at the code, it appears that the same machinery that's used to
merge a freed block with its two neighbors could be used here.  An
untested version that attempts to do that is attached below, with the
added code marked.

Is this something that is worth considering for v2.04?


void *
realloc(void *ptr, size_t size)
{
  BLOCK *b;
  char *newptr;
  size_t copysize;

  if (ptr == 0)
    return malloc(size);

  b = (BLOCK *)((char *)ptr-4);
  copysize = b->size & ~1;
  if (size <= copysize)
  {
    return ptr;
  }
  /* **** Begin new code **** */
  else if (! (AFTER (b)->size & 1) && copysize + AFTER (b)->size >= size)
  {
    if (copysize + AFTER (b)->size >= size + MIN_SAVE_EXTRA)
    {
      if (slop)
      {
        int bslop = b2bucket (slop);

	slop->next = freelist[bslop];
	freelist[bslop] = slop;
      }
      slop = split_block (b, size - copysize);
    }
    merge (b, AFTER (b), AFTER (b));
    return ptr;
  }
  /* **** End new code **** */

  newptr = (char *)malloc(size);
  if (newptr)
  {
    memcpy(newptr, ptr, copysize);
    free(ptr);
  }
  return newptr;
}

---------- Forwarded message ----------
Date: Mon, 16 Aug 1999 20:05:41 -0400
From: G <msk11 AT cornell DOT edu>
To: djgpp AT delorie DOT com
Newgroups: comp.os.msdos.djgpp
Subject: Possible Bug in realloc()

Hi there,
   I've been using DJGPP for a couple of months now and am very impressed by
it. Thanks to all of you who put forth all of the effort necessary to create
it! I think that I may have come across a bug, however. When I was looking
through the source code for realloc() I found the following lines in the
code for realloc() :
newptr= (char *)malloc(size);
.
.
.
memcpy(newptr, ptr, copysize);
free(ptr);
return newptr;

   It appears to me that when malloc is unable to allocate the requested
amount of memory and returns NULL, data from the old block of memory(whose
address is ptr) is copied to offset 0. I stepped through the code with RHIDE
and this is what appears to happen. I'm pretty sure this is not what was
intended. Of course, this is easy to fix by checking the newptr!=0 before
the copy. Please let me know if I have made a mistake here.
   Also, while on the subject, may I suggest a new function similar to
realloc() that also changes the size of a memory block and copies data if
necessary, but one the keeps the old block of memory reserved if it cannot
allocate a larger block. This would be very useful for times when one is
building a growing set of data and doesn't want to lose it all when it can't
be made any larger. I have thought of writing a function that does this
using exising memory allocation functions such as malloc() but the problem
with this approach is illustrated by the following example:
   Let's say you have 600 total units of space on the computer.
   Say 300 units are allocated in 1 large block and the subsequent 300 are
free.
   If you want to enlarge the first block to 500 units, a "smart" realloc()
could just enlarge the 300 unit block to 500 units if no block were already
using the 200 units of space immediately following the 300 unit block.
Malloc(), on the other hand would only see 300 free units(not knowing the
300 units already used could be part of the necessary 500) and so would deny
the request for a 500 unit block whereas a "smart" reallloc could grant it.
Unfortunately I don't know enogh of the internals of DJGPP memory blocks to
write such a function, but if anyone has such a function I would love to
know about it.
   Thanks for your time, I hope I have been of some help.
G. Kashan
kashan AT aecom DOT yu DOT edu



- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019