Mail Archives: djgpp/1995/10/16/03:52:42
>When realloc returns NULL, it really frees the memory block that the
>pointer originally had? The knowledge of the right answer is very
>important for the memory management in C.
The answer is probably No. Why, because what does realloc do?
1) if requested size <= actual size of allocated block then
return same block. //Note that actual size of allocated block
//is only gauranteed to be greater than or
//equal to original requested size.
2) temp = malloc( requested size)
3) if !temp return null // Haven't freed old block yet.
4) move data from old block to new block.
5) free old block
6) return temp
>********************
>If the answer is YES,
>********************
>
>The following code, compiled with DJGPP should produce a protection
>fault, but it does not (it seems to run perfectly)
But even if the answer was yes, C is a hostile place.
You stuff up, C gives you no protection, not even an error message.
It will let you scribble over a freed block quite happily. Note that
free'ing a block doesn't deallocate that virtual memory. Malloc
usually holds on to it on the basis that you will want some more
memory later... This is probably bad news in a multitasking
environment but that is what we have large swap files for. Note that
free has a pass by value parameter. There is no way free() can set
the pointer passed to zero. (Wouldn't really help anyway, there are
too many ways to get around such a protection)
>********************
>If the answer is NO,
>********************
>it seems to me a problem with the C language, because there is no way to
>free this memory block unless you save the original pointer.
Not the first and certainly not the last problem.
Hokay the way to answer this is to grab the source code for malloc.c
and have a look.
Here is realloc from \src\libgplus\src\malloc.c...
-----------------------------------------------------------
void* realloc(void* mem, size_t bytes)
{
if (mem == 0)
return malloc(bytes);
else
{
size_t nb = request2size(bytes);
mchunkptr p = mem2chunk(mem);
size_t oldsize;
long room;
mchunkptr nxt;
if (p == returned_list) /* support realloc-last-freed-chunk
idiocy */
returned_list = returned_list->fd;
clear_inuse(p);
oldsize = p->size;
/* try to expand (even if already big enough), to clean up chunk
*/
free_returned_list(); /* make freed chunks available to
consolidate */
while (!inuse(nxt = next_chunk(p))) /* Expand the chunk forward */
{
unlink(nxt);
set_size(p, p->size + nxt->size);
}
room = p->size - nb;
if (room >= 0) /* Successful expansion */
{
if (room >= MINSIZE) /* give some back if possible */
{
mchunkptr remainder = (mchunkptr)((char*)(p) + nb);
set_size(remainder, room);
cleanlink(remainder);
set_size(p, nb);
}
set_inuse(p);
return chunk2mem(p);
}
else /* Could not expand. Get another chunk and copy. */
{
void* newmem;
size_t count;
size_t* src;
size_t* dst;
set_inuse(p); /* don't let malloc consolidate us yet! */
newmem = malloc(nb);
/* Copy -- we know that alignment is at least `size_t' */
src = (size_t*) mem;
dst = (size_t*) newmem;
count = (oldsize - SIZE_SZ) / sizeof(size_t);
while (count-- > 0) *dst++ = *src++;
free(mem);
return newmem;
}
}
}
----------------------------------------------------------------------
Whoops! BUG!
They don't check to see if the malloc is successful! Although this
version has so many macros, they may have that hidden in a define
somewhere. But certainly the free( mem) is done after the malloc
newmem.
Hmm. Lets see if the other malloc.c is better behaved. (Yes there are
two malloc.c in the src code for DJGPP.)
This one is from libsrc\c\lib\malloc.c
-------------------------------------------------
void *
realloc(cp, nbytes)
void *cp;
size_t nbytes;
{
register u_int onb;
register int i;
union overhead *op;
char *res;
int was_alloced = 0;
if (cp == NULL)
return (malloc(nbytes));
op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
if (op->ov_magic == MAGIC) {
was_alloced++;
i = op->ov_index;
} else {
/*
* Already free, doing "compaction".
*
* Search for the old block of memory on the
* free list. First, check the most common
* case (last element free'd), then (this failing)
* the last ``realloc_srchlen'' items free'd.
* If all lookups fail, then assume the size of
* the memory block being realloc'd is the
* largest possible (so that all "nbytes" of new
* memory are copied into). Note that this could cause
* a memory fault if the old area was tiny, and the moon
* is gibbous. However, that is very unlikely.
*/
if ((i = findbucket(op, 1)) < 0 &&
(i = findbucket(op, realloc_srchlen)) < 0)
i = NBUCKETS;
}
onb = 1 << (i + 3);
if (onb < pagesz)
onb -= sizeof (*op) + RSLOP;
else
onb += pagesz - sizeof (*op) - RSLOP;
/* avoid the copy if same size block */
if (was_alloced) {
if (i) {
i = 1 << (i + 2);
if (i < pagesz)
i -= sizeof (*op) + RSLOP;
else
i += pagesz - sizeof (*op) - RSLOP;
}
if (nbytes <= onb && nbytes > i) {
#ifdef RCHECK
op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
*(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
#endif
return(cp);
} else
free(cp);
}
if ((res = malloc(nbytes)) == NULL)
return (NULL);
if (cp != res) /* common optimization if "compacting" */
bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
return (res);
}
--------------------------------------
Aha! This one cheats slightly. It frees first, then copies. Here it
even relies on the fact that free() doesn't deallocate virtual memory.
At least it checks to see if malloc was sucessful.
Try to sleep well as you think on the dictum...
"If builders built as programmers wrote, then the first woodpecker
that came along would destroy all of civilization."
John Carter
Institute for Water Quality Studies. Department of Water Affairs.
Internet : ece AT dwaf-hri DOT pwv DOT gov DOT za Phone : 27-12-808-0374x194
Fax : 27-12-808-0338 [Host for Afwater list server]
Let's keep this matter in perspective. One insignificant galaxy, one
of the thousands of millions of galaxies, has a small yellow sun on
its outer rim. About this sun orbits a molten iron ball. On the
surface of this ball is a very thin crust of silica slag. This crust
is partly coated by a microscopically thin layer of carbon hydrogen
compounds. Some of which has delusions of grandeur.
- Raw text -