bug in malloc() under OS 3.3
Chris Wagner
jwag at moose.asd.sgi.com
Thu Jul 19 12:24:25 AEST 1990
In article <7401 at amelia.nas.nasa.gov>, plessel at prandtl.nas.nasa.gov
(Todd C. Plessel) writes:
> bug in malloc() under OS 3.3 any help would be appreciated
> =============================== cut here =================================
> /*
> * testmem.c - test memory allocation/usage/freeing using malloc() & free()
> *
> * Todd Plessel
> * NASA Ames Research Center
> * (415) 604-4474
> *
> * This program demonstrates some serious bugs with the memory management
> * rountines and/or the window manager on IRIS systems.
> *
> * On a 3000 or 4DG or GTX running 3.1 the following problem exists:
> *
> * If all the memory gets allocated, the window manager dies completely.
> *
> * On a 4DG or GTX running 3.2 the following problem exists:
> *
> * If all the memory gets allocated, the window manager kills the window
> * (and all processes running out of it) where the program was run from.
> *
> * Note: both of these problems will not occur every time the program is
> * run, but will always occur within 10 tries.
> * Also note that ulimit(3, 0) returns a negative value (it broken).
> *
> *
> * On a VGX running 3.3 the following problem exists:
> *
> * ulimit(3, 0) returns a bad value (about 800MB) but more importantly,
> * malloc() allows up to about 500MB to be allocated!
> * But when this data is actually filled, the program gets killed after
> * about 75MB.
> *
> * To compile this program:
> *
> * cc -o testmem testmem.c
> *
> * or to use libmalloc:
> *
> * cc -o testmem testmem.c -lmalloc
> *
> * To run:
> *
> * testmem
> * (just press return at each prompt)
> *
> * (It makes no difference if we link with libmalloc or not)
> *
> */
>
> /*------------------------------- INCLUDES
---------------------------------*/
>
> #include <stdio.h>
> /* makes no difference if we use this and -lmalloc or not */
> #include <malloc.h>
>
> /*-------------------------------- DEFINES
---------------------------------*/
>
> /* useful byte sizes */
>
> #define _1B 1
> #define _2B 2
> #define _4B 4
> #define _8B 8
> #define _16B 16
> #define _32B 32
> #define _64B 64
> #define _128B 128
> #define _256B 256
> #define _512B 512
> #define _1KB 1024
> #define _2KB 2048
> #define _4KB 4096
> #define _8KB 8192
> #define _16KB 16384
> #define _32KB 32768
> #define _64KB 65536
> #define _128KB 131072
> #define _256KB 262144
> #define _512KB 524288
> #define _1MB 1048576
> #define _2MB 2097152
> #define _4MB 4194304
> #define _8MB 8388608
> #define _16MB 16777216
> #define _32MB 33554432
> #define _64MB 67108864
> #define _128MB 134217728
> #define _256MB 268435456
> #define _512MB 536870912
> #define _1GB 1073741824
>
>
> /*
> * MAX_CHUNKS is the maximum number of mallocs that can be stored
> * CHUNK_SIZE is the INITIAL number of bytes to request with each malloc()
> * THRESHHOLD is the minimum number of bytes to request before giving up
> *
> * If CHUNK_SIZE bytes are not available then half as many bytes are
> * requested (repeatedly) until:
> * (1) a successful malloc occurs or
> * (2) we have reached the THRESHHOLD - i.e., we would be requesting less
> * than THRESHHOLD bytes to malloc)
> */
>
>
> #define MAX_CHUNKS 5000
> #define CHUNK_SIZE _1MB
> #define THRESHHOLD _1KB
>
> /*------------------------------- main
-------------------------------------*/
>
> main()
> {
> char *addr[MAX_CHUNKS]; /* stores allocated chunks */
> int dims[MAX_CHUNKS]; /* holds each chunk size in addr[] */
> char *p; /* temp pointer to a[i] for filling */
> int i; /* looping index on a[] */
> int j; /* inner loop index for filling */
> int num_chunks; /* holds number of chunks allocated */
> long chunk_size = CHUNK_SIZE;/* size (in bytes) to request */
> long threshhold = THRESHHOLD;/* min # of bytes to request */
> long total = 0; /* total # of bytes allcoated */
> char str[80]; /* temp string for input */
> int chunk_limit = MAX_CHUNKS;/* max # of chunks to attempt */
> /* this is an optional chicken exit */
> /* the default is NO LIMIT */
>
>
>
>
>
>
>
> printf("\n\n TESTMEM\n\n");
> printf(" A program for testing memory allocation/useage/freeing\n");
> printf(" using the standard UNIX functions malloc() and free()\n\n");
>
> printf("System info:\n");
> printf("Memory limit = %ld\n", ulimit(3, 0));
> printf("Current break point = %d\n\n", sbrk(0));
>
> printf("To use the default values in [] just press <RETURN>\n\n");
>
> str[0] = '\0';
> printf("Enter the CHUNK SIZE (# of bytes per malloc) [%ld] : ",
> CHUNK_SIZE);
> gets(str);
>
> if (str[0] != '\0')
> {
> chunk_size = (long) atoi(str);
>
> if (chunk_size <= 0)
> chunk_size = CHUNK_SIZE;
> }
>
> str[0] = '\0';
> printf("Enter the THRESHHOLD (minimum # of bytes to malloc) [%ld] : ",
> threshhold);
> gets(str);
>
> if (str[0] != '\0')
> {
> threshhold = (long) atoi(str);
>
> if (threshhold <= 0)
> threshhold = THRESHHOLD;
> }
>
> str[0] = '\0';
> printf("Enter the CHUNK LIMIT (maximum # of chunks to attempt) ");
> printf("[NO LIMIT] : ");
> gets(str);
>
> if (str[0] != '\0')
> {
> chunk_limit = atoi(str);
>
> if (chunk_limit <= 0)
> chunk_limit = MAX_CHUNKS;
> }
>
> printf("\n");
> i = 0;
>
> while (1)
> {
> addr[i] = (char *) malloc (chunk_size);
>
> if (addr[i] == (char *) NULL)
> {
> if (chunk_size > threshhold)
> {
> chunk_size /= 2;
> continue;
> }
>
> else
> {
> printf("Out of memory after %d mallocs.\n",
> i + 1);
> break;
> }
> }
>
> printf("i = %3d (of %d): allocated %ld bytes.\n",
> i + 1, chunk_limit, chunk_size);
> total += chunk_size;
> dims[i] = chunk_size;
> ++i;
>
> if (i == MAX_CHUNKS)
> {
> printf("Ran out of places to store chunks!\n");
> printf("Recompile and/or run this program again with\n");
> printf("MAX_CHUNKS > %d and/or CHUNK_SIZE > %d\n",
> MAX_CHUNKS, chunk_size);
> break;
> }
>
> if (i == chunk_limit)
> {
> printf("Quitting now while I'm ahead...\n");
> break;
> }
>
> }
>
> num_chunks = i;
>
> printf("A total of %ld bytes were allocated in %d chunks.\n",
> total, num_chunks);
>
> str[0] = '\0';
> printf("Do you want to fill the bytes with data [No] ? ");
> gets(str);
>
> if (str[0] == 'y' || str[0] == 'Y')
> {
> for (i = 0; i < num_chunks; ++i)
> {
> printf("i = %3d (of %d): filling %ld bytes...",
> i + 1, num_chunks, dims[i]);
>
> p = addr[i];
>
> for (j = 0; j < dims[i]; ++j)
> *p++ = 'A';
>
> printf("\n");
> }
>
> printf("Finished filling.\n");
> }
>
> str[0] = '\0';
> printf("Do you want to free the bytes [No] ? ");
> gets(str);
>
> if (str[0] == 'y' || str[0] == 'Y')
> {
> for (i = 0; i < num_chunks; ++i)
> {
> printf("i = %3d (of %d): freeing %ld bytes...",
> i + 1, num_chunks, dims[i]);
> free((char *) addr[i]);
> printf("\n");
> }
>
> printf("Finished freeing.\n");
> }
>
> printf("Exiting gracefully...\n\n\n");
>
> }
>
>
>
> /*------------------------- END OF FILE testmem.c
--------------------------*/
It does appear that ulimit(3) is broken on 3.3
Howver the other part isn't really broke - the system comes shipped by
default with
a MAXUMEM - the maximum virtual size of a process - at 512Mb. This
maximum can be
set lower either system wide by reconfiguring the system or per process
by using setrlimit.
We permit a process to allocate up to MAXUMEM of virtual space -
allowing a user for example
to alloc sparse matrices, or fork a large process. Only if the process
USES all the memory, then
we need a place to store it (swap space) If there is not enough swap
space, the process
is killed. To avoid a process getting killed, reduce the maximum size
permitted.
The real bottom line here is that ulimit(3) is basically worthless - it
is a time dependent
number in any case, and of course gives one no clue as to whether the
value returned
will cause your process the thrash the main memory or not..
Chris Wagner
More information about the Comp.sys.sgi
mailing list