\ ***************************************************************************** \ * Copyright (c) 2011 IBM Corporation \ * All rights reserved. \ * This program and the accompanying materials \ * are made available under the terms of the BSD License \ * which accompanies this distribution, and is available at \ * http://www.opensource.org/licenses/bsd-license.php \ * \ * Contributors: \ * IBM Corporation - initial implementation \ ****************************************************************************/ \ * Dynamic memory allocation/de-allocation debug functions \ ***************************************************************************** \ Uncomment the following code for debugging bad write accesses beyond \ the end of the allocated block: \ Store magic value past the end of the block during alloc-mem and \ check for this magic value when free-mem has been called. #if 1 : alloc-mem ( len -- addr ) dup /n + alloc-mem ( len addr ) 2dup + 3141592653589793 swap ! nip ; : free-mem ( addr len -- ) 2dup + @ 3141592653589793 <> IF cr ." Detected memory corrupt during free-mem of " swap . . cr EXIT THEN /n + free-mem ; #endif \ Never ever assume that allocated memory is pre-initialized with 0 ... : alloc-mem ( len -- addr ) dup alloc-mem swap 2dup ff fill drop ; \ Make sure that memory block do not contain "valid" data after free-mem: : free-mem ( addr len -- ) 2dup ff fill free-mem ; \ The following definitions are used for debugging the parameters of free-mem: \ Store block address and size of allocated blocks \ in an array, then check for right values on free-mem. 1000 CONSTANT max-malloced-blocks CREATE malloced-blocks max-malloced-blocks 2 * cells allot malloced-blocks max-malloced-blocks 2 * cells erase : alloc-mem ( len -- addr ) dup alloc-mem dup 0= IF cr ." alloc-mem returned 0 for size " swap . cr EXIT THEN ( len addr ) malloced-blocks max-malloced-blocks 0 DO ( len addr m-blocks-ptr ) dup @ 0= IF ( len addr m-blocks-ptr ) \ Found a free entry: store addr and len over >r dup >r ! r> cell+ ! r> UNLOOP EXIT THEN cell+ cell+ ( len addr next-m-blocks-ptr ) LOOP ." Please increase max-malloced-blocks." cr ( len addr next-m-blocks-ptr ) drop nip ; : free-mem ( addr len -- ) malloced-blocks max-malloced-blocks 0 DO ( addr len m-blocks-ptr ) dup @ ?dup IF ( addr len m-blocks-ptr s-addr ) 3 pick = IF ( addr len m-blocks-ptr ) dup cell+ @ ( addr len m-blocks-ptr s-len ) 2 pick = IF ( addr len m-blocks-ptr ) \ All right, addr and len matched, \ clear entry and call original free-mem. dup cell+ 0 swap ! 0 swap ! free-mem ELSE >r swap cr ." free-mem called for block " . ." with wrong size=" . cr ." ( correct size should be: " r> cell+ @ . ." )" cr THEN UNLOOP EXIT THEN ( addr len m-blocks-ptr ) THEN cell+ cell+ ( addr len next-m-blocks-ptr ) LOOP drop swap cr ." free-mem called for block " . ." ( size=" . ." ) which has never been allocated before!" cr ; \ Enable these for verbose debug messages: #if 0 : alloc-mem cr ." alloc-mem with len=" dup . alloc-mem ." returned addr=" dup . cr ; : free-mem cr ." free mem addr=" over . ." len=" dup . cr free-mem ; #endif