[comp.windows.x] SUMMARY: Error: Cannot realloc

ecollins@NMSU.EDU (08/16/90)

Summary:

A couple of weeks ago I posted a question concerning the message:
Error: Cannot perform realloc.

Since several people expressed interest and since the information is
generally useful I've included the best response and some example
code.


Symptoms(from initial posting):

I have a good sized Athena Widget based program which creates
toplevelshells for things such as help and various other options.  If
I select one of these options as soon as the initial screen comes up
then the toplevelshells are created and everything works fine.  I can
make use of the functions provided by these shells for the remainder
of the program and I can pop the shells down at any time without a problem.

If I do some text processing ( including message passing with a Prolog
process using named pipes ) and then try to use one of the options
that generate a new toplevelshell I get the following message:

Error: Cannot perform realloc.

Sometimes I get the error, sometimes I don't, but typically I'll get a
core dump at this point. If I don't select a toplevelshell option the
program runs fine.  I only allocate memory dynamically in one place
and I'm sure that I free it properly when I'm done with it. I find it
hard to believe that I'm running out of virtual memory...

1.  Is there a way to programmatically monitor the available free
    memory as I execute the program so that I can see where memory
    is being used up?  How?

2.  I'm declaring several large character arrays inside lower level 
    functions.  Is it more memory efficient to declare these as global
    static arrays rather than auto arrays local to the function?

3.  Are there certain types of programming errors that typically cause
    the above problem?

----------------------------------------------------------
Here is the most useful response I received:

From: kay@cs.jhu.edu (Jon Kay)
To: ecollins@nmsu.edu
Subject: Error: Cannot perform realloc.

	To me, that message translates to the following: 
"Hey, Mr. Programmer!  You have a stray pointer, and it's messing with my
(malloc's) internal data structures!"  If you are running under System V
or SunOS, there is a nifty function called malloc_verify() which will make sure
that the current malloc data structure is consistent.  You can use this to
track down the exact location of the bug (it's really great!).  The manual
pages to read are malloc(3) under SunOS and malloc(3X) under System V.
	You can nail down the exact amount of memory that has been used so far
via the following incantaion: printf("%d bytes used\n", sbrk(0) - &end);
Declare "extern char end;" in each such file (end is defined by ld to be the
end of the program before any memory is malloc'ed.  Read the sbrk(2) and
end(3) manual pages for more information).
	Auto arrays  are intrinsically more efficient if you can get away with
them (they are nice because of the automatic and painless deallocation), but
depending on the OS you can get into trouble if they are very large (say, 10K.
Possibly less on older Unices).

----------------------------------------------------------------------------
Good advice. Thanks Jon, for answering q's 1, 2 and more.

I got rid of my problem by cleaning up several functions and replacing
a large chunk of code -- including my malloc/free code. I never did
narrow it down to an exact statement.

Here's one possible cause for q3:

I had an error in some code that dealt with a radio group of toggle
widgets ( Athena ).  When you select a member of a radio group, all
callbacks registered for the previously selected member get called
along with actions and callbacks for the newly selected member.  I
allocated in the callback of the first selected toggle button and
deallocated the second time it was entered.  Unfortunately, my
flagging mechanism did not catch all possible cases and it was
possible to come up with mismatched mallocs and frees. In any case I
cleaned that code up and opted for a static char array instead of
malloc/free.  I suspect this to have been my problem.

Here's some generally useful code based on Jon's recommendations and 
malloc(3).

/*=========================================================================
**
** memtest --
**     Example code to show the use of memory allocation routines.
**
** Notes: ( SunOS 4.1 )
**     Depends on malloc.o and mallocmap.o files from /usr/lib/debug.
**     
**     See malloc(3) for more info.
**     
** Makefile:
**     CC = /bin/cc
**     CFLAGS = -target sun3
**     memtest: memtest.c
**	           $(CC) $(CFLAGS) -o memtest memtest.c malloc.o mallocmap.o 
**
** Modification       Author                 Date         Description
** ------------       ------                 ----         -----------
**     ---            EMC, NMSU              29-Jul-90    original
**
**======================================================================*/

#include <stdio.h>
#include <sys/types.h>

void ShowMemUsed();
void SetMallocDebugLevel();
void CheckMalloc();
void DisplayHeapMap();

/*==============================*/

main()
{

	caddr_t sbrk();
    extern char end;
	char *buffer0, *buffer1, *buffer2;
	
	ShowMemUsed( "Before any mallocs" );
	DisplayHeapMap();

	SetMallocDebugLevel( 2 );
	ShowMemUsed( "After setting malloc debug level" );

	buffer0 = ( char * ) malloc( 10 );
	ShowMemUsed( "After one 10 byte malloc" );

	CheckMalloc();

	buffer1 = ( char * ) malloc( 17000 );  
	ShowMemUsed( "After a second malloc of 17000 bytes" );
	DisplayHeapMap();

}

/*==============================*/

void
ShowMemUsed( message )
char *message;
{
	caddr_t sbrk();
    extern char end;

	printf( "\n%s: %d bytes used\n", message, sbrk(0) - &end );
}	

/*==============================*/

void
DisplayHeapMap()
{
	printf("\n==============================\nStart of Heap Map:\n" );
	mallocmap();
	printf("End of Heap Map.\n==============================\n" );
}

/*==============================*/

void 
SetMallocDebugLevel( level )
int level;
{
	int oldLevel;	

	oldLevel = malloc_debug( level );

	printf( "\nOld Malloc debug level: %d\nNew Malloc debug level: %d\n",
		   oldLevel, level );
}

/*==============================*/

void 
CheckMalloc()
{
	printf( "\nChecking malloc structure for errors...\n" );
    if ( malloc_verify() )
		printf( "No errors were found.\n" );
	else
		printf( "Errors were detected!\n" );
}


Also, thanks go to Mark Leisher for suggesting the use of Xscope.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
=  Mike Collins                   | "Why would I want to change my    =
=  New Mexico State University    |  mind?  Is there something wrong  =
=  e-mail: ecollins@nmsu.edu      |  with the one I have?" -- Spock   =
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=