[comp.lang.c] Indirection and MALLOC

SXSAW%ALASKA.BITNET@wiscvm.wisc.EDU (05/12/87)

For those people using malloc to do the incredible indirection....
  First off - you don't need a dissassembler to look at the MACRO code that
C produces.  When you invoke the C compiler, simply do a
   $ CC/LIST/MACHINE src-file
The C compiler will then create a src-file.LIS which has the machine code
interspersed with the source code (VERY HANDY) - see HELP CC for more
information (this of course assumes you are using DEC's C).
  Second - don't use MALLOC, malloc is a) not ast re-entrent, and b) probably
incorrectly coded - I say probably since I have been unable to get CSC to
confirm a few tidbits of info for me.  The C manual states that the
allocation/deallocation routines will keep the last FREE'd block for possible
re-use in a subsequent MALLOC - This works great as long as the routines
DON'T decide to break up the block of memory - which they will happily do,
i.e. If the chunk requested is smaller than what is saved, it breaks off
only the chunk requested - keeping the leftovers for subsequent calls to
MALLOC - the fun starts when they call LIB$FREE_VM to release these "chunks".
The RTL manual states in BIG BOLD LETTERS that "Thou shalt not LIB$FREE_VM
partial blocks which were allocated via LIB$GET_VM".  Maybe the C developers
know something about GET_VM and FREE_VM that we don't??  Note that I AM
NOT saying that this is in fact the problem - just that it may be a POTENTIAL
problem.
  Re AST re-entrency - Since the alloc/dealloc routines save the size and
address of FREE'd blocks across calls - to manipulate later, and since the
code can be interrupted during this manipulation via an AST routine which
calls MALLOC - well.......  It only takes about 10 lines of code to create
a test case for this that WILL FAIL sometimes - and sometimes not, depends
on the timing. (with this type of coding going on in the CRTL I begin to
wonder about other routines)  I have generally found that with VMS4.x and
the additional features added to  LIB$GET_VM, etc. (i.e. the memory ZONE
concepts) - that the best way to go is use the RTL procedures.  naturally
you code will be less portable, but....
  Just a side note - I would be really surprised if the compiler is incorrectly
handling the indirection.  Indirection is easy for a compiler to do on a VAX
and also easy for the programmer to "mess up" - all it takes is one "bad" link.
Something you might try (common debugging technique) is to reduce the code
to its bare essentials, that is just the code necessary to do the MALLOC's
and build your links - easy to test.

levy@ttrdc.UUCP (Daniel R. Levy) (05/13/87)

In article <7331@brl-adm.ARPA>, SXSAW%ALASKA.BITNET@wiscvm.wisc.EDU writes:
<   Re AST re-entrency - Since the alloc/dealloc routines save the size and
< address of FREE'd blocks across calls - to manipulate later, and since the
< code can be interrupted during this manipulation via an AST routine which
< calls MALLOC - well.......  It only takes about 10 lines of code to create
< a test case for this that WILL FAIL sometimes - and sometimes not, depends
< on the timing. (with this type of coding going on in the CRTL I begin to
< wonder about other routines)  I have generally found that with VMS4.x and
< the additional features added to  LIB$GET_VM, etc. (i.e. the memory ZONE
< concepts) - that the best way to go is use the RTL procedures.  naturally
< you code will be less portable, but....

It is not a good idea to use malloc() re-entrantly in an interrupt
service routine even on a UNIX system.  The code below illustrates the
problem on a System V release 2 3B20 (will core dump with a memory fault)
when run and given rapidly repeated keyboard interrupts, unless PROTECT_MALLOC
is #define'd.  This ought to work just fine on VMS, too.

--------
#include <signal.h>
main()
{
	int astrtn();
	int i;
	char *malloc();
	char *c;
	void exit();

	(void) signal(SIGINT,astrtn);
	for (;;) {
#ifdef PROTECT_MALLOC
		(void) signal(SIGINT,SIG_IGN);
#endif
		if (!(c=malloc((unsigned)100))) {
			(void) write(1,"malloc() failure\n",(unsigned)17);
			exit(1);
		}
#ifdef PROTECT_MALLOC
		(void) signal(SIGINT,astrtn);
#endif
		for (i=0; i<100; i++)
			*c++ = 'y';
	}
}

astrtn()
{
	char *d;
	char *malloc();
	void exit();
	int i;

	(void) signal(SIGINT,SIG_IGN);
	(void) write(1,"INTERRUPT\n",(unsigned)10);
	if (!(d=malloc((unsigned)100))) {
		(void) write(1,"astrtn malloc failure\n",(unsigned)22);
		exit(2);
	}
	for (i=0; i<100; i++)
		*d++ = 'x';
	(void) signal(SIGINT,astrtn);
	return 0;
}
--------
-- 
|------------dan levy------------|  Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
|         an engihacker @        |		vax135}!ttrdc!ttrda!levy
| at&t computer systems division |  Disclaimer:  try datclaimer.
|--------skokie, illinois--------|