Index: src/libcfa/heap.c
===================================================================
--- src/libcfa/heap.c	(revision a4248de1c62a74f682562616679c2e37a51aeb53)
+++ src/libcfa/heap.c	(revision 5d4fa18bc4bff0eb87535bc141fa9ffb76a6b33d)
@@ -10,6 +10,6 @@
 // Created On       : Tue Dec 19 21:58:35 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Jul 26 22:28:23 2018
-// Update Count     : 449
+// Last Modified On : Tue Jul 31 18:08:50 2018
+// Update Count     : 470
 // 
 
@@ -94,21 +94,40 @@
 
 
-// static _Bool prtHeapTerm = false;
-
-// inline _Bool prtHeapTerm() {
-// 	return prtHeapTerm;
-// } // prtHeapTerm
-
-// _Bool prtHeapTermOn() {
-// 	_Bool temp = traceHeap;
-// 	traceHeap = true;
+static _Bool checkFree = false;
+
+inline _Bool checkFree() {
+	return checkFree;
+} // checkFree
+
+_Bool checkFreeOn() {
+	_Bool temp = checkFree;
+	checkFree = true;
+	return temp;
+} // checkFreeOn
+
+_Bool checkFreeOff() {
+	_Bool temp = checkFree;
+	checkFree = false;
+	return temp;
+} // checkFreeOff
+
+
+// static _Bool traceHeapTerm = false;
+
+// inline _Bool traceHeapTerm() {
+// 	return traceHeapTerm;
+// } // traceHeapTerm
+
+// _Bool traceHeapTermOn() {
+// 	_Bool temp = traceHeapTerm;
+// 	traceHeapTerm = true;
 // 	return temp;
-// } // prtHeapTermOn
-
-// _Bool prtHeapTermOff() {
-// 	_Bool temp = traceHeap;
-// 	traceHeap = false;
+// } // traceHeapTermOn
+
+// _Bool traceHeapTermOff() {
+// 	_Bool temp = traceHeapTerm;
+// 	traceHeapTerm = false;
 // 	return temp;
-// } // prtHeapTermOff
+// } // traceHeapTermOff
 
 
@@ -139,31 +158,4 @@
 } // extern "C"
 #endif // __CFA_DEBUG__
-
-
-// statically allocated variables => zero filled.
-
-static size_t pageSize;									// architecture pagesize
-static size_t heapExpand;								// sbrk advance
-static size_t mmapStart;								// cross over point for mmap
-static unsigned int maxBucketsUsed;						// maximum number of buckets in use
-static unsigned int bucketSizes[NoBucketSizes] = {		// different bucket sizes
-    16, 32, 48, 64,
-    80, 96, 112, 128, 144, 160, 192, 224,
-    256, 320, 384, 448, 512, 640, 768, 896,
-    1024, 1536, 2048, 2560, 3072, 3584, 4096, 6144,
-    8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360,
-    16384, 18432, 20480, 22528, 24576, 26624, 28672, 30720,
-    32768, 36864, 40960, 45056, 49152, 53248, 57344, 61440,
-    65536, 73728, 81920, 90112, 98304, 106496, 114688, 122880,
-    131072, 147456, 163840, 180224, 196608, 212992, 229376, 245760,
-    262144, 294912, 327680, 360448, 393216, 425984, 458752, 491520,
-    524288, 655360, 786432, 917504, 1048576, 1179648, 1310720, 1441792,
-    1572864, 1703936, 1835008, 1966080, 2097152, 2621440, 3145728, 3670016,
-    4194304
-};
-#ifdef FASTLOOKUP
-static unsigned char lookup[LookupSizes];				// O(1) lookup for small sizes
-#endif // FASTLOOKUP
-static int mmapFd = -1;									// fake or actual fd for anonymous file
 
 
@@ -240,4 +232,40 @@
 }; // HeapManager
 
+static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
+// statically allocated variables => zero filled.
+
+
+static size_t pageSize;									// architecture pagesize
+static size_t heapExpand;								// sbrk advance
+static size_t mmapStart;								// cross over point for mmap
+static unsigned int maxBucketsUsed;						// maximum number of buckets in use
+
+// Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size.
+static unsigned int bucketSizes[NoBucketSizes] @= {		// different bucket sizes
+    16, 32, 48, 64,
+    64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224,
+    256 + sizeof(HeapManager.Storage), 320, 384, 448, 512 + sizeof(HeapManager.Storage), 640, 768, 896,
+    1_024 + sizeof(HeapManager.Storage), 1_536, 2_048 + sizeof(HeapManager.Storage), 2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), 6_144,
+    8_192 + sizeof(HeapManager.Storage), 9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360,
+    16_384 + sizeof(HeapManager.Storage), 18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720,
+    32_768 + sizeof(HeapManager.Storage), 36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440,
+    65_536 + sizeof(HeapManager.Storage), 73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880,
+    131_072 + sizeof(HeapManager.Storage), 147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760,
+    262_144 + sizeof(HeapManager.Storage), 294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520,
+    524_288 + sizeof(HeapManager.Storage), 655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), 1_179_648, 1_310_720, 1_441_792,
+    1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), 2_621_440, 3_145_728, 3_670_016,
+    4_194_304 + sizeof(HeapManager.Storage)
+};
+#ifdef FASTLOOKUP
+static unsigned char lookup[LookupSizes];				// O(1) lookup for small sizes
+#endif // FASTLOOKUP
+static int mmapFd = -1;									// fake or actual fd for anonymous file
+
+
+#ifdef __CFA_DEBUG__
+static _Bool heapBoot = 0;								// detect recursion during boot
+#endif // __CFA_DEBUG__
+static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
+
 
 static inline _Bool setMmapStart( size_t value ) {
@@ -281,16 +309,11 @@
 static void ^?{}( HeapManager & ) {
 	#ifdef __STATISTICS__
-	// if ( prtHeapTerm() ) {
+	// if ( traceHeapTerm() ) {
 	// 	printStats();
-	// 	checkFree( heapManager, true );
+	// 	if ( checkfree() ) checkFree( heapManager, true );
 	// } // if
 	#endif // __STATISTICS__
 } // ~HeapManager
 
-
-#ifdef __CFA_DEBUG__
-static _Bool heapBoot = 0;								// detect recursion during boot
-#endif // __CFA_DEBUG__
-static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
 
 static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
@@ -312,6 +335,4 @@
 	^heapManager{};
 } // memory_shutdown
-
-static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
 
 
@@ -342,26 +363,25 @@
 static void printStats() {
     char helpText[512];
-    int len = snprintf( helpText, 512,
-						"\nHeap statistics:\n"
-						"  malloc: calls %u / storage %llu\n"
-						"  calloc: calls %u / storage %llu\n"
-						"  memalign: calls %u / storage %llu\n"
-						"  cmemalign: calls %u / storage %llu\n"
-						"  realloc: calls %u / storage %llu\n"
-						"  free: calls %u / storage %llu\n"
-						"  mmap: calls %u / storage %llu\n"
-						"  munmap: calls %u / storage %llu\n"
-						"  sbrk: calls %u / storage %llu\n",
-						malloc_calls, malloc_storage,
-						calloc_calls, calloc_storage,
-						memalign_calls, memalign_storage,
-						cmemalign_calls, cmemalign_storage,
-						realloc_calls, realloc_storage,
-						free_calls, free_storage,
-						mmap_calls, mmap_storage,
-						munmap_calls, munmap_storage,
-						sbrk_calls, sbrk_storage
+	__cfaabi_dbg_bits_print_buffer( helpText, 512,
+			"\nHeap statistics:\n"
+			"  malloc: calls %u / storage %llu\n"
+			"  calloc: calls %u / storage %llu\n"
+			"  memalign: calls %u / storage %llu\n"
+			"  cmemalign: calls %u / storage %llu\n"
+			"  realloc: calls %u / storage %llu\n"
+			"  free: calls %u / storage %llu\n"
+			"  mmap: calls %u / storage %llu\n"
+			"  munmap: calls %u / storage %llu\n"
+			"  sbrk: calls %u / storage %llu\n",
+			malloc_calls, malloc_storage,
+			calloc_calls, calloc_storage,
+			memalign_calls, memalign_storage,
+			cmemalign_calls, cmemalign_storage,
+			realloc_calls, realloc_storage,
+			free_calls, free_storage,
+			mmap_calls, mmap_storage,
+			munmap_calls, munmap_storage,
+			sbrk_calls, sbrk_storage
 		);
-    write( statfd, helpText, len );
 } // printStats
 
@@ -637,9 +657,9 @@
 
 
-size_t checkFree( HeapManager & manager, _Bool prt ) with ( manager ) {
+size_t checkFree( HeapManager & manager ) with ( manager ) {
     size_t total = 0;
 	#ifdef __STATISTICS__
     __cfaabi_dbg_bits_acquire();
-    if ( prt ) __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
+    __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
 	#endif // __STATISTICS__
     for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
@@ -659,10 +679,10 @@
 	    } // for
 		#ifdef __STATISTICS__
-	    if ( prt ) __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
+	    __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
 	    if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
 		#endif // __STATISTICS__
 	} // for
 	#ifdef __STATISTICS__
-	if ( prt ) __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
+	__cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
 	__cfaabi_dbg_bits_release();
 	#endif // __STATISTICS__
@@ -922,5 +942,5 @@
 		#ifdef __STATISTICS__
 		printStats();
-		checkFree( heapManager, true );
+		if ( checkFree() ) checkFree( heapManager );
 		#endif // __STATISTICS__
     } // malloc_stats
Index: src/libcfa/stdhdr/malloc.h
===================================================================
--- src/libcfa/stdhdr/malloc.h	(revision a4248de1c62a74f682562616679c2e37a51aeb53)
+++ src/libcfa/stdhdr/malloc.h	(revision 5d4fa18bc4bff0eb87535bc141fa9ffb76a6b33d)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jul 20 15:58:16 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jul 23 18:20:32 2018
-// Update Count     : 8
+// Last Modified On : Tue Jul 31 10:01:10 2018
+// Update Count     : 9
 // 
 
@@ -17,4 +17,17 @@
 size_t default_mmap_start();							// CFA extras
 size_t default_heap_expansion();
+
+_Bool traceHeap();
+_Bool traceHeapOn();
+_Bool traceHeapOff();
+
+_Bool traceHeapTerm();
+_Bool traceHeapTermOn();
+_Bool traceHeapTermOff();
+
+_Bool checkFree();
+_Bool checkFreeOn();
+_Bool checkFreeOff();
+
 extern "C" {
 size_t malloc_alignment( void * );
Index: src/tests/heap.c
===================================================================
--- src/tests/heap.c	(revision 5d4fa18bc4bff0eb87535bc141fa9ffb76a6b33d)
+++ src/tests/heap.c	(revision 5d4fa18bc4bff0eb87535bc141fa9ffb76a6b33d)
@@ -0,0 +1,342 @@
+#include <thread>
+#include <kernel>										// processor
+#include <stdlib>										// *allocs
+#include <malloc.h>										// malloc_*
+
+// #include <time>
+// #define __CFA_DEFAULT_PREEMPTION__ 1000`us
+// //#define __CFA_DEFAULT_PREEMPTION__ 0
+
+// Duration default_preemption() {
+// 	return __CFA_DEFAULT_PREEMPTION__;
+// }
+
+#define __U_DEFAULT_MMAP_START__ (512 * 1024 + 1)
+size_t default_mmap_start() __attribute__(( weak )) {
+    return __U_DEFAULT_MMAP_START__;
+} // default_mmap_start
+
+thread Worker {
+}; // Worker
+
+void main( Worker & ) {
+    enum { NoOfAllocs = 5000, NoOfMmaps = 10 };
+    char *locns[NoOfAllocs];
+    int i;
+
+    // check alloc/free
+
+    for ( int j = 0; j < 40; j += 1 ) {
+		for ( i = 0; i < NoOfAllocs; i += 1 ) {
+			locns[i] = alloc( i );
+			//sout | (void *)locns[i] | endl;
+			for ( int k = 0; k < i; k += 1 ) locns[i][k] = '\345';
+		} // for
+		//sout | (char *)sbrk(0) - start | " bytes" | endl;
+
+		for ( i = 0; i < NoOfAllocs; i += 1 ) {
+			//sout | (void *)locns[i] | endl;
+			for ( int k = 0; k < i; k += 1 ) if ( locns[i][k] != '\345' ) abort( "new/delete corrupt storage1" );
+			free( locns[i] );
+		} // for
+		//sout | (char *)sbrk(0) - start | " bytes" | endl;
+
+		for ( i = 0; i < NoOfAllocs; i += 1 ) {
+			locns[i] = alloc( i );
+			//sout | (void *)locns[i] | endl;
+			for ( int k = 0; k < i; k += 1 ) locns[i][k] = '\345';
+		} // for
+		for ( i = NoOfAllocs - 1; i >=0 ; i -= 1 ) {
+			//sout | (void *)locns[i] | endl;
+			for ( int k = 0; k < i; k += 1 ) if ( locns[i][k] != '\345' ) abort( "new/delete corrupt storage2" );
+			free( locns[i] );
+		} // for
+    } // for
+
+    // check malloc/free (sbrk)
+
+    for ( i = 0; i < NoOfAllocs; i += 1 ) {
+		size_t s = (i + 1) * 20;
+		char *area = (char *)malloc( s );
+		if ( area == 0 ) abort( "malloc/free out of memory" );
+		area[0] = '\345'; area[s - 1] = '\345';			// fill first/last
+		area[malloc_usable_size( area ) - 1] = '\345';	// fill ultimate byte
+		free( area );
+    } // for
+
+    for ( i = 0; i < NoOfAllocs; i += 1 ) {
+		size_t s = i + 1;				// +1 to make initialization simpler
+		locns[i] = (char *)malloc( s );
+		if ( locns[i] == 0 ) abort( "malloc/free out of memory" );
+		locns[i][0] = '\345'; locns[i][s - 1] = '\345';	// fill first/last
+		locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte
+    } // for
+    for ( i = 0; i < NoOfAllocs; i += 1 ) {
+		size_t s = i + 1;
+		if ( locns[i][0] != '\345' || locns[i][s - 1] != '\345' ||
+			 locns[i][malloc_usable_size( locns[i] ) - 1] != '\345' ) abort( "malloc/free corrupt storage" );
+		free( locns[i] );
+    } // for
+
+    // check malloc/free (mmap)
+
+    for ( i = 0; i < NoOfMmaps; i += 1 ) {
+		size_t s = i + default_mmap_start();				// cross over point
+		char *area = (char *)malloc( s );
+		if ( area == 0 ) abort( "malloc/free out of memory" );
+		area[0] = '\345'; area[s - 1] = '\345';			// fill first/last
+		area[malloc_usable_size( area ) - 1] = '\345';	// fill ultimate byte
+		free( area );
+    } // for
+
+    for ( i = 0; i < NoOfMmaps; i += 1 ) {
+		size_t s = i + default_mmap_start();				// cross over point
+		locns[i] = (char *)malloc( s );
+		if ( locns[i] == 0 ) abort( "malloc/free out of memory" );
+		locns[i][0] = '\345'; locns[i][s - 1] = '\345';	// fill first/last
+		locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte
+    } // for
+    for ( i = 0; i < NoOfMmaps; i += 1 ) {
+		size_t s = i + default_mmap_start();				// cross over point
+		if ( locns[i][0] != '\345' || locns[i][s - 1] != '\345' ||
+			 locns[i][malloc_usable_size( locns[i] ) - 1] != '\345' ) abort( "malloc/free corrupt storage" );
+		free( locns[i] );
+    } // for
+
+    // check calloc/free (sbrk)
+
+    for ( i = 0; i < NoOfAllocs; i += 1 ) {
+		size_t s = (i + 1) * 20;
+		char *area = (char *)calloc( 5, s );
+		if ( area == 0 ) abort( "calloc/free out of memory" );
+		if ( area[0] != '\0' || area[s - 1] != '\0' ||
+			 area[malloc_usable_size( area ) - 1] != '\0' ||
+			 ! malloc_zero_fill( area ) ) abort( "calloc/free corrupt storage1" );
+		area[0] = '\345'; area[s - 1] = '\345';			// fill first/last
+		area[malloc_usable_size( area ) - 1] = '\345';	// fill ultimate byte
+		free( area );
+    } // for
+
+    for ( i = 0; i < NoOfAllocs; i += 1 ) {
+		size_t s = i + 1;
+		locns[i] = (char *)calloc( 5, s );
+		if ( locns[i] == 0 ) abort( "calloc/free out of memory" );
+		if ( locns[i][0] != '\0' || locns[i][s - 1] != '\0' ||
+			 locns[i][malloc_usable_size( locns[i] ) - 1] != '\0' ||
+			 ! malloc_zero_fill( locns[i] ) ) abort( "calloc/free corrupt storage2" );
+		locns[i][0] = '\345'; locns[i][s - 1] = '\345';	// fill first/last
+		locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte
+    } // for
+    for ( i = 0; i < NoOfAllocs; i += 1 ) {
+		size_t s = i + 1;
+		if ( locns[i][0] != '\345' || locns[i][s - 1] != '\345' ||
+			 locns[i][malloc_usable_size( locns[i] ) - 1] != '\345' ) abort( "calloc/free corrupt storage3" );
+		free( locns[i] );
+    } // for
+
+    // check calloc/free (mmap)
+
+    for ( i = 0; i < NoOfMmaps; i += 1 ) {
+		size_t s = i + default_mmap_start();				// cross over point
+		char *area = (char *)calloc( 1, s );
+		if ( area == 0 ) abort( "calloc/free out of memory" );
+		if ( area[0] != '\0' || area[s - 1] != '\0' ) abort( "calloc/free corrupt storage4.1" );
+		if ( area[malloc_usable_size( area ) - 1] != '\0' ) abort( "calloc/free corrupt storage4.2" );
+		if ( ! malloc_zero_fill( area ) ) abort( "calloc/free corrupt storage4.3" );
+		area[0] = '\345'; area[s - 1] = '\345';			// fill first/last
+		area[malloc_usable_size( area ) - 1] = '\345';	// fill ultimate byte
+		free( area );
+    } // for
+
+    for ( i = 0; i < NoOfMmaps; i += 1 ) {
+		size_t s = i + default_mmap_start();				// cross over point
+		locns[i] = (char *)calloc( 1, s );
+		if ( locns[i] == 0 ) abort( "calloc/free out of memory" );
+		if ( locns[i][0] != '\0' || locns[i][s - 1] != '\0' ||
+			 locns[i][malloc_usable_size( locns[i] ) - 1] != '\0' ||
+			 ! malloc_zero_fill( locns[i] ) ) abort( "calloc/free corrupt storage5" );
+		locns[i][0] = '\345'; locns[i][s - 1] = '\345';	// fill first/last
+		locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte
+    } // for
+    for ( i = 0; i < NoOfMmaps; i += 1 ) {
+		size_t s = i + default_mmap_start();				// cross over point
+		if ( locns[i][0] != '\345' || locns[i][s - 1] != '\345' ||
+			 locns[i][malloc_usable_size( locns[i] ) - 1] != '\345' ) abort( "calloc/free corrupt storage6" );
+		free( locns[i] );
+    } // for
+
+    // check memalign/free (sbrk)
+
+    enum { limit = 64 * 1024 };							// check alignments up to here
+
+    for ( size_t a = libAlign(); a <= limit; a += a ) {	// generate powers of 2
+		//sout | alignments[a] | endl;
+		for ( int s = 1; s < NoOfAllocs; s += 1 ) {		// allocation of size 0 can return null
+			char *area = (char *)memalign( a, s );
+			if ( area == 0 ) abort( "memalign/free out of memory" );
+			//sout | i | " " | area | endl;
+			if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
+				abort( "memalign/free bad alignment : memalign(%d,%d) = %p", (int)a, s, area );
+			} // if
+			area[0] = '\345'; area[s - 1] = '\345';	// fill first/last byte
+			area[malloc_usable_size( area ) - 1] = '\345'; // fill ultimate byte
+			free( area );
+		} // for
+    } // for
+
+    // check memalign/free (mmap)
+
+    for ( size_t a = libAlign(); a <= limit; a += a ) {	// generate powers of 2
+		//sout | alignments[a] | endl;
+		for ( i = 1; i < NoOfMmaps; i += 1 ) {
+			size_t s = i + default_mmap_start();			// cross over point
+			char *area = (char *)memalign( a, s );
+			if ( area == 0 ) abort( "memalign/free out of memory" );
+			//sout | i | " " | area | endl;
+			if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
+				abort( "memalign/free bad alignment : memalign(%d,%d) = %p", (int)a, (int)s, area );
+			} // if
+			area[0] = '\345'; area[s - 1] = '\345';		// fill first/last byte
+			area[malloc_usable_size( area ) - 1] = '\345'; // fill ultimate byte
+			free( area );
+		} // for
+    } // for
+
+    // check calloc/realloc/free (sbrk)
+
+    for ( i = 1; i < 10000; i += 12 ) {
+		// initial N byte allocation
+		char *area = (char *)calloc( 5, i );
+		if ( area == 0 ) abort( "calloc/realloc/free out of memory" );
+		if ( area[0] != '\0' || area[i - 1] != '\0' ||
+			 area[malloc_usable_size( area ) - 1] != '\0' ||
+			 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage1" );
+
+		// Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
+		for ( int s = i; s < 256 * 1024; s += 26 ) {	// start at initial memory request
+			area = (char *)realloc( area, s );			// attempt to reuse storage
+			if ( area == 0 ) abort( "calloc/realloc/free out of memory" );
+			if ( area[0] != '\0' || area[s - 1] != '\0' ||
+				 area[malloc_usable_size( area ) - 1] != '\0' ||
+				 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage2" );
+		} // for
+		free( area );
+    } // for
+
+    // check calloc/realloc/free (mmap)
+
+    for ( i = 1; i < 1000; i += 12 ) {
+		// initial N byte allocation
+		size_t s = i + default_mmap_start();				// cross over point
+		char *area = (char *)calloc( 1, s );
+		if ( area == 0 ) abort( "calloc/realloc/free out of memory" );
+		if ( area[0] != '\0' || area[s - 1] != '\0' ||
+			 area[malloc_usable_size( area ) - 1] != '\0' ||
+			 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage1" );
+
+		// Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
+		for ( int r = i; r < 256 * 1024; r += 26 ) {	// start at initial memory request
+			area = (char *)realloc( area, r );		// attempt to reuse storage
+			if ( area == 0 ) abort( "calloc/realloc/free out of memory" );
+			if ( area[0] != '\0' || area[r - 1] != '\0' ||
+				 area[malloc_usable_size( area ) - 1] != '\0' ||
+				 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage2" );
+		} // for
+		free( area );
+    } // for
+
+    // check memalign/realloc/free
+
+    size_t amount = 2;
+    for ( size_t a = libAlign(); a <= limit; a += a ) {	// generate powers of 2
+		// initial N byte allocation
+		char *area = (char *)memalign( a, amount );		// aligned N-byte allocation
+		if ( area == 0 ) abort( "memalign/realloc/free out of memory" ); // no storage ?
+		//sout | alignments[a] | " " | area | endl;
+		if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
+			abort( "memalign/realloc/free bad alignment : memalign(%d,%d) = %p", (int)a, (int)amount, area );
+		} // if
+		area[0] = '\345'; area[amount - 2] = '\345';	// fill first/penultimate byte
+
+		// Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
+		for ( int s = amount; s < 256 * 1024; s += 1 ) { // start at initial memory request
+			if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "memalign/realloc/free corrupt storage" );
+			area = (char *)realloc( area, s );			// attempt to reuse storage
+			if ( area == 0 ) abort( "memalign/realloc/free out of memory" ); // no storage ?
+			//sout | i | " " | area | endl;
+			if ( (size_t)area % a != 0 ) {				// check for initial alignment
+				abort( "memalign/realloc/free bad alignment %p", area );
+			} // if
+			area[s - 1] = '\345';						// fill last byte
+		} // for
+		free( area );
+    } // for
+
+    // check cmemalign/free
+
+    for ( size_t a = libAlign(); a <= limit; a += a ) {	// generate powers of 2
+		//sout | alignments[a] | endl;
+		for ( int s = 1; s < limit; s += 1 ) {			// allocation of size 0 can return null
+			char *area = (char *)cmemalign( a, 1, s );
+			if ( area == 0 ) abort( "cmemalign/free out of memory" );
+			//sout | i | " " | area | endl;
+			if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
+				abort( "cmemalign/free bad alignment : cmemalign(%d,%d) = %p", (int)a, s, area );
+			} // if
+			if ( area[0] != '\0' || area[s - 1] != '\0' ||
+				 area[malloc_usable_size( area ) - 1] != '\0' ||
+				 ! malloc_zero_fill( area ) ) abort( "cmemalign/free corrupt storage" );
+			area[0] = '\345'; area[s - 1] = '\345';		// fill first/last byte
+			free( area );
+		} // for
+    } // for
+
+    // check cmemalign/realloc/free
+
+    amount = 2;
+    for ( size_t a = libAlign() + libAlign(); a <= limit; a += a ) { // generate powers of 2
+		// initial N byte allocation
+		char *area = (char *)cmemalign( a, 1, amount );	// aligned N-byte allocation
+		if ( area == 0 ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?
+		//sout | alignments[a] | " " | area | endl;
+		if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
+			abort( "cmemalign/realloc/free bad alignment : cmemalign(%d,%d) = %p", (int)a, (int)amount, area );
+		} // if
+		if ( area[0] != '\0' || area[amount - 1] != '\0' ||
+			 area[malloc_usable_size( area ) - 1] != '\0' ||
+			 ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage1" );
+		area[0] = '\345'; area[amount - 2] = '\345';	// fill first/penultimate byte
+
+		// Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
+		for ( int s = amount; s < 256 * 1024; s += 1 ) { // start at initial memory request
+			if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "cmemalign/realloc/free corrupt storage2" );
+			area = (char *)realloc( area, s );			// attempt to reuse storage
+			if ( area == 0 ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?
+			//sout | i | " " | area | endl;
+			if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
+				abort( "cmemalign/realloc/free bad alignment %p", area );
+			} // if
+			if ( area[s - 1] != '\0' || area[s - 1] != '\0' ||
+				 area[malloc_usable_size( area ) - 1] != '\0' ||
+				 ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage3" );
+			area[s - 1] = '\345';						// fill last byte
+		} // for
+		free( area );
+    } // for
+	//sout | "worker" | thisTask() | "successful completion" | endl;
+} // Worker main
+
+int main() {
+    const unsigned int NoOfWorkers = 4;
+    {
+		processor processors[NoOfWorkers - 1] __attribute__(( unused )); // more than one processor
+		Worker workers[NoOfWorkers] __attribute__(( unused ));
+    }
+	// checkFreeOn();
+    // malloc_stats();
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// compile-command: "cfa -nodebug -O2 heap.c" //
+// End: //
