PRODUCT : Borland C++ NUMBER : 643 VERSION : All OS : PC DOS DATE : October 22, 1993 PAGE : 1/4 TITLE : Using a Dynamically Allocated Stack in C /*[]------------------------------------------------------------[]*/ /*| |*/ /*| 'Using a LARGE temporary stack in a small program' |*/ /*| |*/ /*| |*/ /*| Copyright (c) 1991 by Borland International |*/ /*| All Rights Reserved. |*/ /*| |*/ /*[]------------------------------------------------------------[]*/ /************************************************************************ NOTE: If you want to use the stack-checking code in Turbo C++ or Borland C++ then you must be in the LARGE or HUGE memory model. **********************************************************************/ /* The theory here is the stack checking option generates the following code at the beginning of every function that was compiled with it on: _function proc far push bp mov bp, sp cmp word ptr DGROUP:_stklen, sp ja short @1@74 call far ptr F_OVERFLOW@ @1@74: . ; the rest of the function... . . This is basically checking SP against the stack length and if SP ever becomes greater than _stklen, (which can only happen if you use all the stack space and then wrap SP from seg:0000 to seg:FFFE) then the overflow function gets called. All we are doing is allocating a 66K buffer from farmalloc, normalizing the pointer to get a full segment, saving the old values for ss, sp, and _stklen, setting the new values, and calling the stack-hungry function. PRODUCT : Borland C++ NUMBER : 643 VERSION : All OS : PC DOS DATE : October 22, 1993 PAGE : 2/4 TITLE : Using a Dynamically Allocated Stack in C This can be very useful for qsort() programs that wish to sort very large tables, and don't need 64k of stack all the time. If you don't use stack checking then you can use this trick from any model. */ #if !defined (__LARGE__) #error Must be in the LARGE model! #endif #include #include #include #include #include unsigned _stklen = 2048; // stack = 2k unsigned int goober = 0; char *p; void recurse1 (void) { goober++; cprintf ("\rCalling recurse1() %u ", goober); recurse1 (); } void do_reg (void) { recurse1 (); } void do_alloc (void) { // NOTE: these all MUST be static (or global) because if they were local // the compiler wouldn't be able to access them after we switch // our stacks. static char far *p; PRODUCT : Borland C++ NUMBER : 643 VERSION : All OS : PC DOS DATE : October 22, 1993 PAGE : 3/4 TITLE : Using a Dynamically Allocated Stack in C static unsigned old_ss, old_sp, old_stklen; if ((p = farmalloc (66000L)) == NULL) { printf ("\nNo room to allocate stack buffer!\n"); exit (1); } /* We now have a pointer xxxx:0004. This example will overwrite the bottom and top of the segment. To prevent serious memory corruption, we must allocate a full 64K segment and normalize it ourselves. Now if we corrupt memory at xxxx:0000 or xxxx:FFFF we are still within the buffer we allocated, and thus are safe. This saves us from incurring the overhead of having a HUGE pointer for the address of our buffer. */ (long)p += 0x00010000; // increment segment p -= 4; // set offset to zero // p is now = (xxxx + 1):0000 old_ss = _SS; // save old values old_sp = _SP; old_stklen = _stklen; _stklen = 60000U; // change the stack length (for checking) _SS = FP_SEG (p); // set up our new stack segment _SP = FP_OFF (&(p[_stklen])); // set the stack to the top goober = 0; // reset our counter recurse1(); // call the recursive DEATH function // If we were to get to this point... _SS = old_ss; // reset the values _SP = old_sp; _stklen = old_stklen; (long)p -= (0x00010000 - 4); // set the pointer back to what it was to free it PRODUCT : Borland C++ NUMBER : 643 VERSION : All OS : PC DOS DATE : October 22, 1993 PAGE : 4/4 TITLE : Using a Dynamically Allocated Stack in C free ((void *) p); } int main (void) { cputs ("\n\rBIG Stack Example (c) 1991 by Borland International\r\n"); // do_reg(); // call this function to compare with regular stack do_alloc (); // call this one to allocate a BIG temporary stack return 0; } DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.