Incompatability between memory layout and 'C' runtime library

Richard B. Johnson (root@chaos.analogic.com)
Wed, 27 Jan 1999 17:47:23 -0500 (EST)


There seems to be an incompatibility between the Linux memory layout
and the 'C' runtime library. I am using glibc 2.0.6.

Because of the offset at which main() starts, the maximum available
(virtual) data space from the data segment presented to main is
4,160,444,527 bytes. This is because the maximum 32-bit pointer value
is 0xffffffff. (Program to show these numbers attached).

Because of the offset at which malloc() starts providing data
the maximum available virtual data space is 4,160,444,511 bytes.
This, too, is because the maximum 32-bit pointer value is 0xffffffff.

However, malloc() will allocate 0xffffffff bytes of data! This cannot
possibly happen because the last 134,522,768 bytes can't be addressed!
Note that malloc() takes 'size_t' (unsigned int).

First data address provided is 0x804a790 (134522768)
Virtual memory available is 4160444527 bytes
First data address provided is by malloc 0x804a790 (134522768)
Virtual memory available is 4160444511 bytes

Now, the maximum signed offset (offsets are signed) that I can
add to the pointer, to address the last byte in the data provided
by malloc() is 0x7ffffffe. If I add this, it should work (since
malloc() told me I had 0xffffffff bytes available. Of course it
doesn't. Malloc() should never have allowed more than 4,160,444,511
bytes, virtual or not.

#include <stdio.h>
#include <malloc.h>
char foo;
main()
{
register char *p;
unsigned long bar = 0xffffffff;
bar -= (unsigned long) &foo;
printf("First data address provided is %p (%lu)\n", &foo, &foo);
printf("Virtual memory available is %lu bytes\n", bar);
p = (char *) malloc(bar);
if(p != NULL)
{
bar = 0xffffffff;
bar -= (unsigned long) p;
printf("First data address provided is by malloc %p (%lu)\n", &foo, &foo);
printf("Virtual memory available is %lu bytes\n", bar);
free(p);
p = (char *) malloc(0xffffffff);
if(p != NULL)
{
puts("BUG!");
p += 0x7ffffffe; /* Maximum positive number - 1 */
*p = (char) 0x00; /* segfault */
}
}
}

Flames will not be answered. I am well aware of how virtual memory
works. I am well aware of over-commitment. If malloc() had failed
to provide 0xffffffff bytes of data, and my program instead tried
again to allocate, once allocation did not fail, the memory manager
would have provided only one page of memory so overcommitment would
have worked. Instead, because malloc() tells me that it can do something
that it cannot possibly accomplish, a program allocating large amounts
of sparse memory can't work and will eventually seg-fault.

Cheers,
Dick Johnson
***** FILE SYSTEM WAS MODIFIED *****
Penguin : Linux version 2.1.131 on an i686 machine (400.59 BogoMips).
Warning : It's hard to remain at the trailing edge of technology.
Wisdom : It's not a Y2K problem. It's a Y2Day problem.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/