Date: Sun, 22 Aug 1999 13:14:11 +0300 (IDT) From: Eli Zaretskii X-Sender: eliz AT is To: DJ Delorie cc: djgpp-workers AT delorie DOT com Subject: Possible Bug in realloc() (fwd) Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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 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