Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!elroy.jpl.nasa.gov!decwrl!megatest!djones From: djones@megatest.UUCP (Dave Jones) Newsgroups: comp.lang.c Subject: Re: alloca() portability Message-ID: <14523@goofy.megatest.UUCP> Date: 15 Nov 90 23:20:09 GMT References: <1990Nov09.233527.7489@chinet.chi.il.us> Organization: Megatest Corporation, San Jose, Ca Lines: 61 I don't see using alloca() as a high crime or a misdemeanor, but if you are afraid of being castaway on the Isle of Enemy Computers, where alloca() doesn't work right, you can use a hand-rolled memory allocation package based on a separate stack. That's handy anyway for applications whose data are naturally stackable (or "treeable"), but whose flow of control does not precisely follow the stacking and unstacking. It goes like this: The program obtains pointers into the stack ("stack-marks") and later can free all the memory allocated after the mark was obtained, all it one swell foop. Of course you will usually want the stack to be "virtual" in the sense that it is not really one contiguous section of memory, and it can grow without bound. #include "ut_Lifo.h" typedef struct { int block_size; /* size of stack-sections */ int bytes_left; /* number of bytes free top section */ Lifo free_blocks; /* list of free sections */ Lifo blocks; /* the stack per se. */ }Stack; typedef struct { char* block; /* section of the stack on top at time of mark */ int bytes_left; /* top byte within that section. */ }Stack_mark; The above implementation uses stack-sections all of one size, so the maximum possible request must be known. For the application it was designed for that is no problem. A little bit more overhead, and it could use sections of undetermined size, perhaps growing them by a multiple of 3/2 or 2 as more sections are required. But the one I'm using is built for speed, being approximately as fast as alloc() on the machines it runs on. A note on longjmp's: The purpose of a longjmp is quite similar to poping the memory-stack to a mark: It pops off a bunch of function- activations all at one go when they become unneeded, often because of an error-condition. The code that does the "real" setjmp should obtain the stack-mark and the code that gets longjmp'd to should pop the stack to that point: Stack stack; static Stack_mark stack_mark; static jmp_buf proc_mark; ... if(setjmp(proc_mark) == 0) { stack_mark = Stack_mark_get(&stack); } else { Stack_pop_to_mark(&stack, stack_mark); }