Index: libcfa/src/assert.cfa
===================================================================
--- libcfa/src/assert.cfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/assert.cfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Mon Nov 28 12:27:26 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Jul 20 15:10:26 2017
-// Update Count     : 2
+// Last Modified On : Thu Nov 21 17:09:26 2019
+// Update Count     : 5
 //
 
@@ -17,4 +17,5 @@
 #include <stdarg.h>								// varargs
 #include <stdio.h>								// fprintf
+#include <unistd.h>								// STDERR_FILENO
 #include "bits/debug.hfa"
 
@@ -26,5 +27,5 @@
 	// called by macro assert in assert.h
 	void __assert_fail( const char *assertion, const char *file, unsigned int line, const char *function ) {
-		__cfaabi_dbg_bits_print_safe( CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file );
+		__cfaabi_bits_print_safe( STDERR_FILENO, CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file );
 		abort();
 	}
@@ -32,14 +33,14 @@
 	// called by macro assertf
 	void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) {
-		__cfaabi_dbg_bits_acquire();
-		__cfaabi_dbg_bits_print_nolock( CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file );
+		__cfaabi_bits_acquire();
+		__cfaabi_bits_print_nolock( STDERR_FILENO, CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file );
 
 		va_list args;
 		va_start( args, fmt );
-		__cfaabi_dbg_bits_print_vararg( fmt, args );
+		__cfaabi_bits_print_vararg( STDERR_FILENO, fmt, args );
 		va_end( args );
 
-		__cfaabi_dbg_bits_print_nolock( "\n" );
-		__cfaabi_dbg_bits_release();
+		__cfaabi_bits_print_nolock( STDERR_FILENO, "\n" );
+		__cfaabi_bits_release();
 		abort();
 	}
Index: libcfa/src/bits/align.hfa
===================================================================
--- libcfa/src/bits/align.hfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/bits/align.hfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Mon Nov 28 12:27:26 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 21 23:05:35 2017
-// Update Count     : 2
+// Last Modified On : Sat Nov 16 18:58:22 2019
+// Update Count     : 3
 //
 // This  library is free  software; you  can redistribute  it and/or  modify it
@@ -33,5 +33,7 @@
 
 // Minimum size used to align memory boundaries for memory allocations.
-#define libAlign() (sizeof(double))
+//#define libAlign() (sizeof(double))
+// gcc-7 uses xmms instructions, which require 16 byte alignment.
+#define libAlign() (16)
 
 // Check for power of 2
Index: libcfa/src/bits/debug.cfa
===================================================================
--- libcfa/src/bits/debug.cfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/bits/debug.cfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Thu Mar 30 12:30:01 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Jul 14 22:17:35 2019
-// Update Count     : 4
+// Last Modified On : Thu Nov 21 17:16:30 2019
+// Update Count     : 10
 //
 
@@ -28,5 +28,5 @@
 extern "C" {
 
-	void __cfaabi_dbg_bits_write( const char *in_buffer, int len ) {
+	void __cfaabi_bits_write( int fd, const char *in_buffer, int len ) {
 		// ensure all data is written
 		for ( int count = 0, retcode; count < len; count += retcode ) {
@@ -34,5 +34,5 @@
 
 			for ( ;; ) {
-				retcode = write( STDERR_FILENO, in_buffer, len - count );
+				retcode = write( fd, in_buffer, len - count );
 
 				// not a timer interrupt ?
@@ -44,21 +44,21 @@
 	}
 
-	void __cfaabi_dbg_bits_acquire() __attribute__((__weak__)) {}
-	void __cfaabi_dbg_bits_release() __attribute__((__weak__)) {}
+	void __cfaabi_bits_acquire() __attribute__((__weak__)) {}
+	void __cfaabi_bits_release() __attribute__((__weak__)) {}
 
-	void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) {
+	void __cfaabi_bits_print_safe  ( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) )) {
 		va_list args;
 
 		va_start( args, fmt );
-		__cfaabi_dbg_bits_acquire();
+		__cfaabi_bits_acquire();
 
 		int len = vsnprintf( buffer, buffer_size, fmt, args );
-		__cfaabi_dbg_bits_write( buffer, len );
+		__cfaabi_bits_write( fd, buffer, len );
 
-		__cfaabi_dbg_bits_release();
+		__cfaabi_bits_release();
 		va_end( args );
 	}
 
-	void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) {
+	void __cfaabi_bits_print_nolock( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) )) {
 		va_list args;
 
@@ -66,15 +66,15 @@
 
 		int len = vsnprintf( buffer, buffer_size, fmt, args );
-		__cfaabi_dbg_bits_write( buffer, len );
+		__cfaabi_bits_write( fd, buffer, len );
 
 		va_end( args );
 	}
 
-	void __cfaabi_dbg_bits_print_vararg( const char fmt[], va_list args ) {
+	void __cfaabi_bits_print_vararg( int fd, const char fmt[], va_list args ) {
 		int len = vsnprintf( buffer, buffer_size, fmt, args );
-		__cfaabi_dbg_bits_write( buffer, len );
+		__cfaabi_bits_write( fd, buffer, len );
 	}
 
-	void __cfaabi_dbg_bits_print_buffer( char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) )) {
+	void __cfaabi_bits_print_buffer( int fd, char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 4, 5) )) {
 		va_list args;
 
@@ -82,5 +82,5 @@
 
 		int len = vsnprintf( in_buffer, in_buffer_size, fmt, args );
-		__cfaabi_dbg_bits_write( in_buffer, len );
+		__cfaabi_bits_write( fd, in_buffer, len );
 
 		va_end( args );
Index: libcfa/src/bits/debug.hfa
===================================================================
--- libcfa/src/bits/debug.hfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/bits/debug.hfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Mon Nov 28 12:27:26 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb  8 12:35:19 2018
-// Update Count     : 2
+// Last Modified On : Thu Nov 21 17:06:58 2019
+// Update Count     : 8
 //
 
@@ -38,11 +38,11 @@
 	#include <stdio.h>
 
-      extern void __cfaabi_dbg_bits_write( const char *buffer, int len );
-      extern void __cfaabi_dbg_bits_acquire();
-      extern void __cfaabi_dbg_bits_release();
-      extern void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) ));
-      extern void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) ));
-      extern void __cfaabi_dbg_bits_print_vararg( const char fmt[], va_list arg );
-      extern void __cfaabi_dbg_bits_print_buffer( char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) ));
+	extern void __cfaabi_bits_write( int fd, const char *buffer, int len );
+	extern void __cfaabi_bits_acquire();
+	extern void __cfaabi_bits_release();
+	extern void __cfaabi_bits_print_safe  ( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) ));
+	extern void __cfaabi_bits_print_nolock( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) ));
+	extern void __cfaabi_bits_print_vararg( int fd, const char fmt[], va_list arg );
+	extern void __cfaabi_bits_print_buffer( int fd, char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 4, 5) ));
 #ifdef __cforall
 }
@@ -50,12 +50,12 @@
 
 #ifdef __CFA_DEBUG_PRINT__
-	#define __cfaabi_dbg_write( buffer, len )         __cfaabi_dbg_bits_write( buffer, len )
-	#define __cfaabi_dbg_acquire()                    __cfaabi_dbg_bits_acquire()
-	#define __cfaabi_dbg_release()                    __cfaabi_dbg_bits_release()
-	#define __cfaabi_dbg_print_safe(...)              __cfaabi_dbg_bits_print_safe   (__VA_ARGS__)
-	#define __cfaabi_dbg_print_nolock(...)            __cfaabi_dbg_bits_print_nolock (__VA_ARGS__)
-	#define __cfaabi_dbg_print_buffer(...)            __cfaabi_dbg_bits_print_buffer (__VA_ARGS__)
-	#define __cfaabi_dbg_print_buffer_decl(...)       char __dbg_text[256]; int __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_bits_write( __dbg_text, __dbg_len );
-	#define __cfaabi_dbg_print_buffer_local(...)      __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_bits_write( __dbg_text, __dbg_len );
+	#define __cfaabi_dbg_write( buffer, len )         __cfaabi_bits_write( STDERR_FILENO, buffer, len )
+	#define __cfaabi_dbg_acquire()                    __cfaabi_bits_acquire()
+	#define __cfaabi_dbg_release()                    __cfaabi_bits_release()
+	#define __cfaabi_dbg_print_safe(...)              __cfaabi_bits_print_safe   (__VA_ARGS__)
+	#define __cfaabi_dbg_print_nolock(...)            __cfaabi_bits_print_nolock (__VA_ARGS__)
+	#define __cfaabi_dbg_print_buffer(...)            __cfaabi_bits_print_buffer (__VA_ARGS__)
+	#define __cfaabi_dbg_print_buffer_decl(...)       char __dbg_text[256]; int __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_bits_write( __dbg_text, __dbg_len );
+	#define __cfaabi_dbg_print_buffer_local(...)      __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_write( __dbg_text, __dbg_len );
 #else
 	#define __cfaabi_dbg_write(...)               ((void)0)
Index: libcfa/src/concurrency/kernel.cfa
===================================================================
--- libcfa/src/concurrency/kernel.cfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/concurrency/kernel.cfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Tue Jan 17 12:27:26 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Jun 20 17:21:23 2019
-// Update Count     : 25
+// Last Modified On : Thu Nov 21 16:46:59 2019
+// Update Count     : 27
 //
 
@@ -841,17 +841,17 @@
 	if(thrd) {
 		int len = snprintf( abort_text, abort_text_size, "Error occurred while executing thread %.256s (%p)", thrd->self_cor.name, thrd );
-		__cfaabi_dbg_bits_write( abort_text, len );
+		__cfaabi_bits_write( STDERR_FILENO, abort_text, len );
 
 		if ( &thrd->self_cor != thrd->curr_cor ) {
 			len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", thrd->curr_cor->name, thrd->curr_cor );
-			__cfaabi_dbg_bits_write( abort_text, len );
+			__cfaabi_bits_write( STDERR_FILENO, abort_text, len );
 		}
 		else {
-			__cfaabi_dbg_bits_write( ".\n", 2 );
+			__cfaabi_bits_write( STDERR_FILENO, ".\n", 2 );
 		}
 	}
 	else {
 		int len = snprintf( abort_text, abort_text_size, "Error occurred outside of any thread.\n" );
-		__cfaabi_dbg_bits_write( abort_text, len );
+		__cfaabi_bits_write( STDERR_FILENO, abort_text, len );
 	}
 }
@@ -864,9 +864,9 @@
 
 extern "C" {
-	void __cfaabi_dbg_bits_acquire() {
+	void __cfaabi_bits_acquire() {
 		lock( kernel_debug_lock __cfaabi_dbg_ctx2 );
 	}
 
-	void __cfaabi_dbg_bits_release() {
+	void __cfaabi_bits_release() {
 		unlock( kernel_debug_lock );
 	}
Index: libcfa/src/heap.cfa
===================================================================
--- libcfa/src/heap.cfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/heap.cfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Tue Dec 19 21:58:35 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Oct 18 07:42:09 2019
-// Update Count     : 556
+// Last Modified On : Sun Nov 24 17:56:15 2019
+// Update Count     : 638
 //
 
@@ -18,4 +18,5 @@
 #include <stdio.h>										// snprintf, fileno
 #include <errno.h>										// errno
+#include <string.h>										// memset, memcpy
 extern "C" {
 #include <sys/mman.h>									// mmap, munmap
@@ -27,7 +28,8 @@
 #include "bits/locks.hfa"								// __spinlock_t
 #include "startup.hfa"									// STARTUP_PRIORITY_MEMORY
-#include "stdlib.hfa"									// bsearchl
+//#include "stdlib.hfa"									// bsearchl
 #include "malloc.h"
 
+#define MIN(x, y) (y > x ? x : y)
 
 static bool traceHeap = false;
@@ -50,21 +52,21 @@
 
 
-static bool checkFree = false;
-
-inline bool checkFree() {
-	return checkFree;
-} // checkFree
-
-bool checkFreeOn() {
-	bool temp = checkFree;
-	checkFree = true;
+static bool prtFree = false;
+
+inline bool prtFree() {
+	return prtFree;
+} // prtFree
+
+bool prtFreeOn() {
+	bool temp = prtFree;
+	prtFree = true;
 	return temp;
-} // checkFreeOn
-
-bool checkFreeOff() {
-	bool temp = checkFree;
-	checkFree = false;
+} // prtFreeOn
+
+bool prtFreeOff() {
+	bool temp = prtFree;
+	prtFree = false;
 	return temp;
-} // checkFreeOff
+} // prtFreeOff
 
 
@@ -89,6 +91,11 @@
 
 enum {
+	// Define the default extension heap amount in units of bytes. When the uC++ supplied heap reaches the brk address,
+	// the brk address is extended by the extension amount.
+	__CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),
+
+	// Define the mmap crossover point during allocation. Allocations less than this amount are allocated from buckets;
+	// values greater than or equal to this value are mmap from the operating system.
 	__CFA_DEFAULT_MMAP_START__ = (512 * 1024 + 1),
-	__CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),
 };
 
@@ -105,5 +112,5 @@
 static unsigned int allocFree;							// running total of allocations minus frees
 
-static void checkUnfreed() {
+static void prtUnfreed() {
 	if ( allocFree != 0 ) {
 		// DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
@@ -112,7 +119,7 @@
 		// 					"Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
 		// 					(long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
-		// __cfaabi_dbg_bits_write( helpText, len );
-	} // if
-} // checkUnfreed
+		// __cfaabi_dbg_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
+	} // if
+} // prtUnfreed
 
 extern "C" {
@@ -123,8 +130,9 @@
 	void heapAppStop() {								// called by __cfaabi_appready_startdown
 		fclose( stdin ); fclose( stdout );
-		checkUnfreed();
+		prtUnfreed();
 	} // heapAppStop
 } // extern "C"
 #endif // __CFA_DEBUG__
+
 
 // statically allocated variables => zero filled.
@@ -134,7 +142,4 @@
 static unsigned int maxBucketsUsed;						// maximum number of buckets in use
 
-
-// #comment TD : This defined is significantly different from the __ALIGN__ define from locks.hfa
-#define ALIGN 16
 
 #define SPINLOCK 0
@@ -147,5 +152,5 @@
 // Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
 // Break recusion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
-enum { NoBucketSizes = 93 };							// number of buckets sizes
+enum { NoBucketSizes = 91 };							// number of buckets sizes
 
 struct HeapManager {
@@ -194,9 +199,9 @@
 			} kind; // Kind
 		} header; // Header
-		char pad[ALIGN - sizeof( Header )];
+		char pad[libAlign() - sizeof( Header )];
 		char data[0];									// storage
 	}; // Storage
 
-	static_assert( ALIGN >= sizeof( Storage ), "ALIGN < sizeof( Storage )" );
+	static_assert( libAlign() >= sizeof( Storage ), "libAlign() < sizeof( Storage )" );
 
 	struct FreeHeader {
@@ -228,19 +233,24 @@
 #define __STATISTICS__
 
+// Bucket size must be multiple of 16.
 // Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size.
 static const unsigned int bucketSizes[] @= {			// 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)
+	16, 32, 48, 64 + sizeof(HeapManager.Storage), // 4
+	96, 112, 128 + sizeof(HeapManager.Storage), // 3
+	160, 192, 224, 256 + sizeof(HeapManager.Storage), // 4
+	320, 384, 448, 512 + sizeof(HeapManager.Storage), // 4
+	640, 768, 896, 1_024 + sizeof(HeapManager.Storage), // 4
+	1_536, 2_048 + sizeof(HeapManager.Storage), // 2
+	2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), // 4
+	6_144, 8_192 + sizeof(HeapManager.Storage), // 2
+	9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(HeapManager.Storage), // 8
+	18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(HeapManager.Storage), // 8
+	36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(HeapManager.Storage), // 8
+	73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(HeapManager.Storage), // 8
+	147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(HeapManager.Storage), // 8
+	294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(HeapManager.Storage), // 8
+	655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), // 4
+	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), // 8
+	2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(HeapManager.Storage), // 4
 };
 
@@ -251,7 +261,6 @@
 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
@@ -259,76 +268,8 @@
 static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
 
-// #comment TD : The return type of this function should be commented
-static inline bool setMmapStart( size_t value ) {
-  if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
-	mmapStart = value;									// set global
-
-	// find the closest bucket size less than or equal to the mmapStart size
-	maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
-	assert( maxBucketsUsed < NoBucketSizes );			// subscript failure ?
-	assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
-	return false;
-} // setMmapStart
-
-
-static void ?{}( HeapManager & manager ) with ( manager ) {
-	pageSize = sysconf( _SC_PAGESIZE );
-
-	for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
-		freeLists[i].blockSize = bucketSizes[i];
-	} // for
-
-	#ifdef FASTLOOKUP
-	unsigned int idx = 0;
-	for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
-		if ( i > bucketSizes[idx] ) idx += 1;
-		lookup[i] = idx;
-	} // for
-	#endif // FASTLOOKUP
-
-	if ( setMmapStart( default_mmap_start() ) ) {
-		abort( "HeapManager : internal error, mmap start initialization failure." );
-	} // if
-	heapExpand = default_heap_expansion();
-
-	char * End = (char *)sbrk( 0 );
-	sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
-	heapBegin = heapEnd = sbrk( 0 );					// get new start point
-} // HeapManager
-
-
-static void ^?{}( HeapManager & ) {
-	#ifdef __STATISTICS__
-	// if ( traceHeapTerm() ) {
-	// 	printStats();
-	// 	if ( checkfree() ) checkFree( heapManager, true );
-	// } // if
-	#endif // __STATISTICS__
-} // ~HeapManager
-
-
-static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
-void memory_startup( void ) {
-	#ifdef __CFA_DEBUG__
-	if ( unlikely( heapBoot ) ) {						// check for recursion during system boot
-		// DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
-		abort( "boot() : internal error, recursively invoked during system boot." );
-	} // if
-	heapBoot = true;
-	#endif // __CFA_DEBUG__
-
-	//assert( heapManager.heapBegin != 0 );
-	//heapManager{};
-	if ( heapManager.heapBegin == 0 ) heapManager{};
-} // memory_startup
-
-static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
-void memory_shutdown( void ) {
-	^heapManager{};
-} // memory_shutdown
-
 
 #ifdef __STATISTICS__
-static unsigned long long int mmap_storage;				// heap statistics counters
+// Heap statistics counters.
+static unsigned long long int mmap_storage;
 static unsigned int mmap_calls;
 static unsigned long long int munmap_storage;
@@ -348,12 +289,11 @@
 static unsigned long long int realloc_storage;
 static unsigned int realloc_calls;
-
-static int statfd;										// statistics file descriptor (changed by malloc_stats_fd)
-
+// Statistics file descriptor (changed by malloc_stats_fd).
+static int statfd = STDERR_FILENO;						// default stderr
 
 // Use "write" because streams may be shutdown when calls are made.
 static void printStats() {
 	char helpText[512];
-	__cfaabi_dbg_bits_print_buffer( helpText, sizeof(helpText),
+	__cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
 									"\nHeap statistics:\n"
 									"  malloc: calls %u / storage %llu\n"
@@ -405,7 +345,9 @@
 						sbrk_calls, sbrk_storage
 		);
-	return write( fileno( stream ), helpText, len );	// -1 => error
+	__cfaabi_bits_write( fileno( stream ), helpText, len );	// ensures all bytes written or exit
+	return len;
 } // printStatsXML
 #endif // __STATISTICS__
+
 
 // #comment TD : Is this the samething as Out-of-Memory?
@@ -418,6 +360,6 @@
 
 static inline void checkAlign( size_t alignment ) {
-	if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) {
-		abort( "Alignment %zu for memory allocation is less than sizeof(void *) and/or not a power of 2.", alignment );
+	if ( alignment < libAlign() || ! libPow2( alignment ) ) {
+		abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );
 	} // if
 } // checkAlign
@@ -431,94 +373,5 @@
 
 
-static inline void checkHeader( bool check, const char * name, void * addr ) {
-	if ( unlikely( check ) ) {							// bad address ?
-		abort( "Attempt to %s storage %p with address outside the heap.\n"
-			   "Possible cause is duplicate free on same block or overwriting of memory.",
-			   name, addr );
-	} // if
-} // checkHeader
-
-// #comment TD : function should be commented and/or have a more evocative name
-//               this isn't either a check or a constructor which is what I would expect this function to be
-static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & size, size_t & alignment ) {
-	if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
-		size_t offset = header->kind.fake.offset;
-		alignment = header->kind.fake.alignment & -2;	// remove flag from value
-		#ifdef __CFA_DEBUG__
-		checkAlign( alignment );						// check alignment
-		#endif // __CFA_DEBUG__
-		header = (HeapManager.Storage.Header *)((char *)header - offset);
-	} // if
-} // fakeHeader
-
-// #comment TD : Why is this a define
-#define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
-
-static inline bool headers( const char * name, void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
-	header = headerAddr( addr );
-
-	if ( unlikely( heapEnd < addr ) ) {					// mmapped ?
-		fakeHeader( header, size, alignment );
-		size = header->kind.real.blockSize & -3;		// mmap size
-		return true;
-	} // if
-
-	#ifdef __CFA_DEBUG__
-	checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
-	#endif // __CFA_DEBUG__
-
-	// #comment TD : This code looks weird...
-	//               It's called as the first statement of both branches of the last if, with the same parameters in all cases
-
-	// header may be safe to dereference
-	fakeHeader( header, size, alignment );
-	#ifdef __CFA_DEBUG__
-	checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
-	#endif // __CFA_DEBUG__
-
-	freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
-	#ifdef __CFA_DEBUG__
-	if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
-		abort( "Attempt to %s storage %p with corrupted header.\n"
-			   "Possible cause is duplicate free on same block or overwriting of header information.",
-			   name, addr );
-	} // if
-	#endif // __CFA_DEBUG__
-	size = freeElem->blockSize;
-	return false;
-} // headers
-
-
-static inline void * extend( size_t size ) with ( heapManager ) {
-	lock( extlock __cfaabi_dbg_ctx2 );
-	ptrdiff_t rem = heapRemaining - size;
-	if ( rem < 0 ) {
-		// If the size requested is bigger than the current remaining storage, increase the size of the heap.
-
-		size_t increase = libCeiling( size > heapExpand ? size : heapExpand, libAlign() );
-		if ( sbrk( increase ) == (void *)-1 ) {
-			unlock( extlock );
-			errno = ENOMEM;
-			return 0;
-		} // if
-		#ifdef __STATISTICS__
-		sbrk_calls += 1;
-		sbrk_storage += increase;
-		#endif // __STATISTICS__
-		#ifdef __CFA_DEBUG__
-		// Set new memory to garbage so subsequent uninitialized usages might fail.
-		memset( (char *)heapEnd + heapRemaining, '\377', increase );
-		#endif // __CFA_DEBUG__
-		rem = heapRemaining + increase - size;
-	} // if
-
-	HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
-	heapRemaining = rem;
-	heapEnd = (char *)heapEnd + size;
-	unlock( extlock );
-	return block;
-} // extend
-
-
+// thunk problem
 size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
 	size_t l = 0, m, h = dim;
@@ -535,4 +388,117 @@
 
 
+static inline bool setMmapStart( size_t value ) {		// true => mmapped, false => sbrk
+  if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
+	mmapStart = value;									// set global
+
+	// find the closest bucket size less than or equal to the mmapStart size
+	maxBucketsUsed = Bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
+	assert( maxBucketsUsed < NoBucketSizes );			// subscript failure ?
+	assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
+	return false;
+} // setMmapStart
+
+
+static inline void checkHeader( bool check, const char * name, void * addr ) {
+	if ( unlikely( check ) ) {							// bad address ?
+		abort( "Attempt to %s storage %p with address outside the heap.\n"
+			   "Possible cause is duplicate free on same block or overwriting of memory.",
+			   name, addr );
+	} // if
+} // checkHeader
+
+
+static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & alignment ) {
+	if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
+		size_t offset = header->kind.fake.offset;
+		alignment = header->kind.fake.alignment & -2;	// remove flag from value
+		#ifdef __CFA_DEBUG__
+		checkAlign( alignment );						// check alignment
+		#endif // __CFA_DEBUG__
+		header = (HeapManager.Storage.Header *)((char *)header - offset);
+	} // if
+} // fakeHeader
+
+
+// <-------+----------------------------------------------------> bsize (bucket size)
+// |header |addr
+//==================================================================================
+//                                | alignment
+// <-----------------<------------+-----------------------------> bsize (bucket size)
+//                   |fake-header | addr
+#define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
+
+// <-------<<--------------------- dsize ---------------------->> bsize (bucket size)
+// |header |addr
+//==================================================================================
+//                                | alignment
+// <------------------------------<<---------- dsize --------->>> bsize (bucket size)
+//                   |fake-header |addr
+#define dataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header ))
+
+
+static inline bool headers( const char * name __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
+	header = headerAddr( addr );
+
+	if ( unlikely( heapEnd < addr ) ) {					// mmapped ?
+		fakeHeader( header, alignment );
+		size = header->kind.real.blockSize & -3;		// mmap size
+		return true;
+	} // if
+
+	#ifdef __CFA_DEBUG__
+	checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
+	#endif // __CFA_DEBUG__
+
+	// header may be safe to dereference
+	fakeHeader( header, alignment );
+	#ifdef __CFA_DEBUG__
+	checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
+	#endif // __CFA_DEBUG__
+
+	freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
+	#ifdef __CFA_DEBUG__
+	if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
+		abort( "Attempt to %s storage %p with corrupted header.\n"
+			   "Possible cause is duplicate free on same block or overwriting of header information.",
+			   name, addr );
+	} // if
+	#endif // __CFA_DEBUG__
+	size = freeElem->blockSize;
+	return false;
+} // headers
+
+
+static inline void * extend( size_t size ) with ( heapManager ) {
+	lock( extlock __cfaabi_dbg_ctx2 );
+	ptrdiff_t rem = heapRemaining - size;
+	if ( rem < 0 ) {
+		// If the size requested is bigger than the current remaining storage, increase the size of the heap.
+
+		size_t increase = libCeiling( size > heapExpand ? size : heapExpand, libAlign() );
+		if ( sbrk( increase ) == (void *)-1 ) {
+			unlock( extlock );
+			errno = ENOMEM;
+			return 0p;
+		} // if
+		#ifdef __STATISTICS__
+		sbrk_calls += 1;
+		sbrk_storage += increase;
+		#endif // __STATISTICS__
+		#ifdef __CFA_DEBUG__
+		// Set new memory to garbage so subsequent uninitialized usages might fail.
+		memset( (char *)heapEnd + heapRemaining, '\377', increase );
+		#endif // __CFA_DEBUG__
+		rem = heapRemaining + increase - size;
+	} // if
+
+	HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
+	heapRemaining = rem;
+	heapEnd = (char *)heapEnd + size;
+	unlock( extlock );
+	return block;
+} // extend
+
+
 static inline void * doMalloc( size_t size ) with ( heapManager ) {
 	HeapManager.Storage * block;						// pointer to new block of storage
@@ -541,5 +507,5 @@
 	// along with the block and is a multiple of the alignment size.
 
-  if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0;
+  if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0p;
 	size_t tsize = size + sizeof(HeapManager.Storage);
 	if ( likely( tsize < mmapStart ) ) {				// small size => sbrk
@@ -574,5 +540,5 @@
 		block = freeElem->freeList.pop();
 		#endif // SPINLOCK
-		if ( unlikely( block == 0 ) ) {					// no free block ?
+		if ( unlikely( block == 0p ) ) {				// no free block ?
 			#if defined( SPINLOCK )
 			unlock( freeElem->lock );
@@ -583,15 +549,15 @@
 
 			block = (HeapManager.Storage *)extend( tsize );	// mutual exclusion on call
-  if ( unlikely( block == 0 ) ) return 0;
-			#if defined( SPINLOCK )
+  if ( unlikely( block == 0p ) ) return 0p;
+		#if defined( SPINLOCK )
 		} else {
 			freeElem->freeList = block->header.kind.real.next;
 			unlock( freeElem->lock );
-			#endif // SPINLOCK
+		#endif // SPINLOCK
 		} // if
 
 		block->header.kind.real.home = freeElem;		// pointer back to free list of apropriate size
 	} else {											// large size => mmap
-  if ( unlikely( size > ~0ul - pageSize ) ) return 0;
+  if ( unlikely( size > ~0ul - pageSize ) ) return 0p;
 		tsize = libCeiling( tsize, pageSize );			// must be multiple of page size
 		#ifdef __STATISTICS__
@@ -611,19 +577,19 @@
 	} // if
 
-	void * area = &(block->data);						// adjust off header to user bytes
+	void * addr = &(block->data);						// adjust off header to user bytes
 
 	#ifdef __CFA_DEBUG__
-	assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
+	assert( ((uintptr_t)addr & (libAlign() - 1)) == 0 ); // minimum alignment ?
 	__atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST );
 	if ( traceHeap() ) {
 		enum { BufferSize = 64 };
 		char helpText[BufferSize];
-		int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
-		// int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
-		__cfaabi_dbg_bits_write( helpText, len );
+		int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize );
+		// int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", addr, size );
+		__cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
 	} // if
 	#endif // __CFA_DEBUG__
 
-	return area;
+	return addr;
 } // doMalloc
 
@@ -631,5 +597,5 @@
 static inline void doFree( void * addr ) with ( heapManager ) {
 	#ifdef __CFA_DEBUG__
-	if ( unlikely( heapManager.heapBegin == 0 ) ) {
+	if ( unlikely( heapManager.heapBegin == 0p ) ) {
 		abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
 	} // if
@@ -677,5 +643,5 @@
 		char helpText[BufferSize];
 		int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
-		__cfaabi_dbg_bits_write( helpText, len );
+		__cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
 	} // if
 	#endif // __CFA_DEBUG__
@@ -683,9 +649,9 @@
 
 
-size_t checkFree( HeapManager & manager ) with ( manager ) {
+size_t prtFree( HeapManager & manager ) with ( manager ) {
 	size_t total = 0;
 	#ifdef __STATISTICS__
-	__cfaabi_dbg_bits_acquire();
-	__cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
+	__cfaabi_bits_acquire();
+	__cfaabi_bits_print_nolock( STDERR_FILENO, "\nBin lists (bin size : free blocks on list)\n" );
 	#endif // __STATISTICS__
 	for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
@@ -696,7 +662,7 @@
 
 		#if defined( SPINLOCK )
-		for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0; p = p->header.kind.real.next ) {
+		for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
 		#else
-		for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0; p = p->header.kind.real.next.top ) {
+		for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {
 		#endif // SPINLOCK
 			total += size;
@@ -707,23 +673,103 @@
 
 		#ifdef __STATISTICS__
-		__cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
-		if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
+		__cfaabi_bits_print_nolock( STDERR_FILENO, "%7zu, %-7u  ", size, N );
+		if ( (i + 1) % 8 == 0 ) __cfaabi_bits_print_nolock( STDERR_FILENO, "\n" );
 		#endif // __STATISTICS__
 	} // for
 	#ifdef __STATISTICS__
-	__cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
-	__cfaabi_dbg_bits_release();
+	__cfaabi_bits_print_nolock( STDERR_FILENO, "\ntotal free blocks:%zu\n", total );
+	__cfaabi_bits_release();
 	#endif // __STATISTICS__
 	return (char *)heapEnd - (char *)heapBegin - total;
-} // checkFree
+} // prtFree
+
+
+static void ?{}( HeapManager & manager ) with ( manager ) {
+	pageSize = sysconf( _SC_PAGESIZE );
+
+	for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
+		freeLists[i].blockSize = bucketSizes[i];
+	} // for
+
+	#ifdef FASTLOOKUP
+	unsigned int idx = 0;
+	for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
+		if ( i > bucketSizes[idx] ) idx += 1;
+		lookup[i] = idx;
+	} // for
+	#endif // FASTLOOKUP
+
+	if ( setMmapStart( default_mmap_start() ) ) {
+		abort( "HeapManager : internal error, mmap start initialization failure." );
+	} // if
+	heapExpand = default_heap_expansion();
+
+	char * end = (char *)sbrk( 0 );
+	sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
+	heapBegin = heapEnd = sbrk( 0 );					// get new start point
+} // HeapManager
+
+
+static void ^?{}( HeapManager & ) {
+	#ifdef __STATISTICS__
+	// if ( traceHeapTerm() ) {
+	// 	printStats();
+	// 	if ( prtfree() ) prtFree( heapManager, true );
+	// } // if
+	#endif // __STATISTICS__
+} // ~HeapManager
+
+
+static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
+void memory_startup( void ) {
+	#ifdef __CFA_DEBUG__
+	if ( unlikely( heapBoot ) ) {						// check for recursion during system boot
+		// DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
+		abort( "boot() : internal error, recursively invoked during system boot." );
+	} // if
+	heapBoot = true;
+	#endif // __CFA_DEBUG__
+
+	//assert( heapManager.heapBegin != 0 );
+	//heapManager{};
+	if ( heapManager.heapBegin == 0p ) heapManager{};
+} // memory_startup
+
+static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
+void memory_shutdown( void ) {
+	^heapManager{};
+} // memory_shutdown
 
 
 static inline void * mallocNoStats( size_t size ) {		// necessary for malloc statistics
 	//assert( heapManager.heapBegin != 0 );
-	if ( unlikely( heapManager.heapBegin == 0 ) ) heapManager{}; // called before memory_startup ?
-	void * area = doMalloc( size );
-	if ( unlikely( area == 0 ) ) errno = ENOMEM;		// POSIX
-	return area;
+	if ( unlikely( heapManager.heapBegin == 0p ) ) heapManager{}; // called before memory_startup ?
+	void * addr = doMalloc( size );
+	if ( unlikely( addr == 0p ) ) errno = ENOMEM;		// POSIX
+	return addr;
 } // mallocNoStats
+
+
+static inline void * callocNoStats( size_t noOfElems, size_t elemSize ) {
+	size_t size = noOfElems * elemSize;
+	char * addr = (char *)mallocNoStats( size );
+  if ( unlikely( addr == 0p ) ) return 0p;
+
+	HeapManager.Storage.Header * header;
+	HeapManager.FreeHeader * freeElem;
+	size_t bsize, alignment;
+	bool mapped __attribute__(( unused )) = headers( "calloc", addr, header, freeElem, bsize, alignment );
+	#ifndef __CFA_DEBUG__
+	// Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
+	if ( ! mapped )
+	#endif // __CFA_DEBUG__
+		// Zero entire data space even when > than size => realloc without a new allocation and zero fill works.
+		// <-------00000000000000000000000000000000000000000000000000000> bsize (bucket size)
+		// `-header`-addr                      `-size
+		memset( addr, '\0', bsize - sizeof(HeapManager.Storage) ); // set to zeros
+
+	header->kind.real.blockSize |= 2;					// mark as zero filled
+	return addr;
+} // callocNoStats
 
 
@@ -745,13 +791,12 @@
 	// subtract libAlign() because it is already the minimum alignment
 	// add sizeof(Storage) for fake header
-	// #comment TD : this is the only place that calls doMalloc without calling mallocNoStats, why ?
-	char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
-  if ( unlikely( area == 0 ) ) return area;
+	char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
+  if ( unlikely( addr == 0p ) ) return addr;
 
 	// address in the block of the "next" alignment address
-	char * user = (char *)libCeiling( (uintptr_t)(area + sizeof(HeapManager.Storage)), alignment );
+	char * user = (char *)libCeiling( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment );
 
 	// address of header from malloc
-	HeapManager.Storage.Header * realHeader = headerAddr( area );
+	HeapManager.Storage.Header * realHeader = headerAddr( addr );
 	// address of fake header * before* the alignment location
 	HeapManager.Storage.Header * fakeHeader = headerAddr( user );
@@ -763,4 +808,23 @@
 	return user;
 } // memalignNoStats
+
+
+static inline void * cmemalignNoStats( size_t alignment, size_t noOfElems, size_t elemSize ) {
+	size_t size = noOfElems * elemSize;
+	char * addr = (char *)memalignNoStats( alignment, size );
+  if ( unlikely( addr == 0p ) ) return 0p;
+	HeapManager.Storage.Header * header;
+	HeapManager.FreeHeader * freeElem;
+	size_t bsize;
+	bool mapped __attribute__(( unused )) = headers( "cmemalign", addr, header, freeElem, bsize, alignment );
+	#ifndef __CFA_DEBUG__
+	// Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
+	if ( ! mapped )
+	#endif // __CFA_DEBUG__
+		memset( addr, '\0', dataStorage( bsize, addr, header ) ); // set to zeros
+	header->kind.real.blockSize |= 2;				// mark as zero filled
+
+	return addr;
+} // cmemalignNoStats
 
 
@@ -776,5 +840,5 @@
 extern "C" {
 	// The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not
-	// initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be
+	// initialized. If size is 0, then malloc() returns either 0p, or a unique pointer value that can later be
 	// successfully passed to free().
 	void * malloc( size_t size ) {
@@ -788,78 +852,42 @@
 
 	// The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to
-	// the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a
+	// the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either 0p, or a
 	// unique pointer value that can later be successfully passed to free().
 	void * calloc( size_t noOfElems, size_t elemSize ) {
-		size_t size = noOfElems * elemSize;
 		#ifdef __STATISTICS__
 		__atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
-		__atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );
-		#endif // __STATISTICS__
-
-		char * area = (char *)mallocNoStats( size );
-	  if ( unlikely( area == 0 ) ) return 0;
+		__atomic_add_fetch( &calloc_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST );
+		#endif // __STATISTICS__
+
+		return callocNoStats( noOfElems, elemSize );
+	} // calloc
+
+	// The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be
+	// unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size
+	// is larger than the old size, the added memory will not be initialized.  If ptr is 0p, then the call is
+	// equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not 0p, then the call
+	// is equivalent to free(ptr). Unless ptr is 0p, it must have been returned by an earlier call to malloc(),
+	// calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.
+	void * realloc( void * oaddr, size_t size ) {
+		#ifdef __STATISTICS__
+		__atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
+		#endif // __STATISTICS__
+
+	  if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
+	  if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size );
 
 		HeapManager.Storage.Header * header;
 		HeapManager.FreeHeader * freeElem;
-		size_t asize, alignment;
-		bool mapped __attribute__(( unused )) = headers( "calloc", area, header, freeElem, asize, alignment );
-		#ifndef __CFA_DEBUG__
-		// Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
-		if ( ! mapped )
-		#endif // __CFA_DEBUG__
-			memset( area, '\0', asize - sizeof(HeapManager.Storage) ); // set to zeros
-
-		header->kind.real.blockSize |= 2;				// mark as zero filled
-		return area;
-	} // calloc
-
-	// #comment TD : Document this function
-	void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
-		size_t size = noOfElems * elemSize;
-		#ifdef __STATISTICS__
-		__atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
-		__atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );
-		#endif // __STATISTICS__
-
-		char * area = (char *)memalignNoStats( alignment, size );
-	  if ( unlikely( area == 0 ) ) return 0;
-		HeapManager.Storage.Header * header;
-		HeapManager.FreeHeader * freeElem;
-		size_t asize;
-		bool mapped __attribute__(( unused )) = headers( "cmemalign", area, header, freeElem, asize, alignment );
-		#ifndef __CFA_DEBUG__
-		// Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
-		if ( ! mapped )
-			#endif // __CFA_DEBUG__
-			memset( area, '\0', asize - ( (char *)area - (char *)header ) ); // set to zeros
-		header->kind.real.blockSize |= 2;				// mark as zero filled
-
-		return area;
-	} // cmemalign
-
-	// The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be
-	// unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size
-	// is larger than the old size, the added memory will not be initialized.  If ptr is NULL, then the call is
-	// equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call
-	// is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(),
-	// calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.
-	void * realloc( void * addr, size_t size ) {
-		#ifdef __STATISTICS__
-		__atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
-		#endif // __STATISTICS__
-
-	  if ( unlikely( addr == 0 ) ) return mallocNoStats( size ); // special cases
-	  if ( unlikely( size == 0 ) ) { free( addr ); return 0; }
-
-		HeapManager.Storage.Header * header;
-		HeapManager.FreeHeader * freeElem;
-		size_t asize, alignment = 0;
-		headers( "realloc", addr, header, freeElem, asize, alignment );
-
-		size_t usize = asize - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
-		if ( usize >= size ) {							// already sufficient storage
+		size_t bsize, oalign = 0;
+		headers( "realloc", oaddr, header, freeElem, bsize, oalign );
+
+		size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
+	  if ( size <= odsize && odsize <= size * 2 ) {	// allow up to 50% wasted storage in smaller size
+			// Do not know size of original allocation => cannot do 0 fill for any additional space because do not know
+			// where to start filling, i.e., do not overwrite existing values in space.
+			//
 			// This case does not result in a new profiler entry because the previous one still exists and it must match with
 			// the free for this memory.  Hence, this realloc does not appear in the profiler output.
-			return addr;
+			return oaddr;
 		} // if
 
@@ -868,24 +896,28 @@
 		#endif // __STATISTICS__
 
-		void * area;
-		if ( unlikely( alignment != 0 ) ) {				// previous request memalign?
-			area = memalign( alignment, size );			// create new aligned area
+		// change size and copy old content to new storage
+
+		void * naddr;
+		if ( unlikely( oalign != 0 ) ) {				// previous request memalign?
+			if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
+				naddr = cmemalignNoStats( oalign, 1, size ); // create new aligned area
+			} else {
+				naddr = memalignNoStats( oalign, size ); // create new aligned area
+			} // if
 		} else {
-			area = mallocNoStats( size );				// create new area
+			if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
+				naddr = callocNoStats( 1, size );		// create new area
+			} else {
+				naddr = mallocNoStats( size );			// create new area
+			} // if
 		} // if
-	  if ( unlikely( area == 0 ) ) return 0;
-		if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill (calloc/cmemalign) ?
-			assert( (header->kind.real.blockSize & 1) == 0 );
-			bool mapped __attribute__(( unused )) = headers( "realloc", area, header, freeElem, asize, alignment );
-			#ifndef __CFA_DEBUG__
-			// Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
-			if ( ! mapped )
-			#endif // __CFA_DEBUG__
-				memset( (char *)area + usize, '\0', asize - ( (char *)area - (char *)header ) - usize ); // zero-fill back part
-			header->kind.real.blockSize |= 2;			// mark new request as zero fill
-		} // if
-		memcpy( area, addr, usize );					// copy bytes
-		free( addr );
-		return area;
+	  if ( unlikely( naddr == 0p ) ) return 0p;
+
+		headers( "realloc", naddr, header, freeElem, bsize, oalign );
+		size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket
+		// To preserve prior fill, the entire bucket must be copied versus the size.
+		memcpy( naddr, oaddr, MIN( odsize, ndsize ) );	// copy bytes
+		free( oaddr );
+		return naddr;
 	} // realloc
 
@@ -898,8 +930,17 @@
 		#endif // __STATISTICS__
 
-		void * area = memalignNoStats( alignment, size );
-
-		return area;
+		return memalignNoStats( alignment, size );
 	} // memalign
+
+
+	// The cmemalign() function is the same as calloc() with memory alignment.
+	void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
+		#ifdef __STATISTICS__
+		__atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
+		__atomic_add_fetch( &cmemalign_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST );
+		#endif // __STATISTICS__
+
+		return cmemalignNoStats( alignment, noOfElems, elemSize );
+	} // cmemalign
 
 	// The function aligned_alloc() is the same as memalign(), except for the added restriction that size should be a
@@ -912,10 +953,10 @@
 	// The function posix_memalign() allocates size bytes and places the address of the allocated memory in *memptr. The
 	// address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of
-	// sizeof(void *). If size is 0, then posix_memalign() returns either NULL, or a unique pointer value that can later
+	// sizeof(void *). If size is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later
 	// be successfully passed to free(3).
 	int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
 	  if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment
 		* memptr = memalign( alignment, size );
-	  if ( unlikely( * memptr == 0 ) ) return ENOMEM;
+	  if ( unlikely( * memptr == 0p ) ) return ENOMEM;
 		return 0;
 	} // posix_memalign
@@ -930,5 +971,5 @@
 	// The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to
 	// malloc(), calloc() or realloc().  Otherwise, or if free(ptr) has already been called before, undefined behavior
-	// occurs. If ptr is NULL, no operation is performed.
+	// occurs. If ptr is 0p, no operation is performed.
 	void free( void * addr ) {
 		#ifdef __STATISTICS__
@@ -936,15 +977,12 @@
 		#endif // __STATISTICS__
 
-		// #comment TD : To decrease nesting I would but the special case in the
-		//               else instead, plus it reads more naturally to have the
-		//               short / normal case instead
-		if ( unlikely( addr == 0 ) ) {					// special case
-			#ifdef __CFA_DEBUG__
-			if ( traceHeap() ) {
-				#define nullmsg "Free( 0x0 ) size:0\n"
-				// Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
-				__cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
-			} // if
-			#endif // __CFA_DEBUG__
+	  if ( unlikely( addr == 0p ) ) {					// special case
+			// #ifdef __CFA_DEBUG__
+			// if ( traceHeap() ) {
+			// 	#define nullmsg "Free( 0x0 ) size:0\n"
+			// 	// Do not debug print free( 0p ), as it can cause recursive entry from sprintf.
+			// 	__cfaabi_dbg_write( nullmsg, sizeof(nullmsg) - 1 );
+			// } // if
+			// #endif // __CFA_DEBUG__
 			return;
 		} // exit
@@ -953,44 +991,8 @@
 	} // free
 
-	// The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see
-	// malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that
-	// parameter.
-	int mallopt( int option, int value ) {
-		choose( option ) {
-		  case M_TOP_PAD:
-			if ( setHeapExpand( value ) ) fallthru default;
-		  case M_MMAP_THRESHOLD:
-			if ( setMmapStart( value ) ) fallthru default;
-		  default:
-			// #comment TD : 1 for unsopported feels wrong
-			return 1;									// success, or unsupported
-		} // switch
-		return 0;										// error
-	} // mallopt
-
-	// The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a
-	// suitable argument).
-	int malloc_trim( size_t ) {
-		return 0;										// => impossible to release memory
-	} // malloc_trim
-
-	// The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to
-	// a block of memory allocated by malloc(3) or a related function.
-	size_t malloc_usable_size( void * addr ) {
-	  if ( unlikely( addr == 0 ) ) return 0;			// null allocation has 0 size
-
-		HeapManager.Storage.Header * header;
-		HeapManager.FreeHeader * freeElem;
-		size_t size, alignment;
-
-		headers( "malloc_usable_size", addr, header, freeElem, size, alignment );
-		size_t usize = size - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
-		return usize;
-	} // malloc_usable_size
-
-
-    // The malloc_alignment() function returns the alignment of the allocation.
+
+	// The malloc_alignment() function returns the alignment of the allocation.
 	size_t malloc_alignment( void * addr ) {
-	  if ( unlikely( addr == 0 ) ) return libAlign();	// minimum alignment
+	  if ( unlikely( addr == 0p ) ) return libAlign();	// minimum alignment
 		HeapManager.Storage.Header * header = headerAddr( addr );
 		if ( (header->kind.fake.alignment & 1) == 1 ) {	// fake header ?
@@ -1002,7 +1004,7 @@
 
 
-    // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc().
+	// The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc().
 	bool malloc_zero_fill( void * addr ) {
-	  if ( unlikely( addr == 0 ) ) return false;		// null allocation is not zero fill
+	  if ( unlikely( addr == 0p ) ) return false;		// null allocation is not zero fill
 		HeapManager.Storage.Header * header = headerAddr( addr );
 		if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
@@ -1013,15 +1015,28 @@
 
 
-    // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and
-    // related functions.
+	// The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to
+	// a block of memory allocated by malloc(3) or a related function.
+	size_t malloc_usable_size( void * addr ) {
+	  if ( unlikely( addr == 0p ) ) return 0;			// null allocation has 0 size
+		HeapManager.Storage.Header * header;
+		HeapManager.FreeHeader * freeElem;
+		size_t bsize, alignment;
+
+		headers( "malloc_usable_size", addr, header, freeElem, bsize, alignment );
+		return dataStorage( bsize, addr, header );	// data storage in bucket
+	} // malloc_usable_size
+
+
+	// The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and
+	// related functions.
 	void malloc_stats( void ) {
 		#ifdef __STATISTICS__
 		printStats();
-		if ( checkFree() ) checkFree( heapManager );
+		if ( prtFree() ) prtFree( heapManager );
 		#endif // __STATISTICS__
 	} // malloc_stats
 
 	// The malloc_stats_fd() function changes the file descripter where malloc_stats() writes the statistics.
-	int malloc_stats_fd( int fd ) {
+	int malloc_stats_fd( int fd __attribute__(( unused )) ) {
 		#ifdef __STATISTICS__
 		int temp = statfd;
@@ -1033,8 +1048,30 @@
 	} // malloc_stats_fd
 
+
+	// The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see
+	// malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that
+	// parameter.
+	int mallopt( int option, int value ) {
+		choose( option ) {
+		  case M_TOP_PAD:
+			if ( setHeapExpand( value ) ) return 1;
+		  case M_MMAP_THRESHOLD:
+			if ( setMmapStart( value ) ) return 1;
+		} // switch
+		return 0;										// error, unsupported
+	} // mallopt
+
+	// The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a
+	// suitable argument).
+	int malloc_trim( size_t ) {
+		return 0;										// => impossible to release memory
+	} // malloc_trim
+
+
 	// The malloc_info() function exports an XML string that describes the current state of the memory-allocation
 	// implementation in the caller.  The string is printed on the file stream stream.  The exported string includes
 	// information about all arenas (see malloc(3)).
 	int malloc_info( int options, FILE * stream ) {
+		if ( options != 0 ) { errno = EINVAL; return -1; }
 		return printStatsXML( stream );
 	} // malloc_info
@@ -1046,5 +1083,5 @@
 	// structure is returned as the function result.  (It is the caller's responsibility to free(3) this memory.)
 	void * malloc_get_state( void ) {
-		return 0;										// unsupported
+		return 0p;										// unsupported
 	} // malloc_get_state
 
@@ -1058,4 +1095,52 @@
 
 
+// Must have CFA linkage to overload with C linkage realloc.
+void * realloc( void * oaddr, size_t nalign, size_t size ) {
+	#ifdef __STATISTICS__
+	__atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
+	#endif // __STATISTICS__
+
+  if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
+  if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size );
+
+	if ( unlikely( nalign == 0 ) ) nalign = libAlign();	// reset alignment to minimum
+	#ifdef __CFA_DEBUG__
+	else
+		checkAlign( nalign );							// check alignment
+	#endif // __CFA_DEBUG__
+
+	HeapManager.Storage.Header * header;
+	HeapManager.FreeHeader * freeElem;
+	size_t bsize, oalign = 0;
+	headers( "realloc", oaddr, header, freeElem, bsize, oalign );
+	size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
+
+  if ( oalign != 0 && (uintptr_t)oaddr % nalign == 0 ) { // has alignment and just happens to work out
+		headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
+		return realloc( oaddr, size );
+	} // if
+
+	#ifdef __STATISTICS__
+	__atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
+	#endif // __STATISTICS__
+
+	// change size and copy old content to new storage
+
+	void * naddr;
+	if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
+		naddr = cmemalignNoStats( nalign, 1, size );	// create new aligned area
+	} else {
+		naddr = memalignNoStats( nalign, size );		// create new aligned area
+	} // if
+
+	headers( "realloc", naddr, header, freeElem, bsize, oalign );
+	size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket
+	// To preserve prior fill, the entire bucket must be copied versus the size.
+	memcpy( naddr, oaddr, MIN( odsize, ndsize ) );		// copy bytes
+	free( oaddr );
+	return naddr;
+} // realloc
+
+
 // Local Variables: //
 // tab-width: 4 //
Index: libcfa/src/interpose.cfa
===================================================================
--- libcfa/src/interpose.cfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/interpose.cfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Wed Mar 29 16:10:31 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Jul 14 22:57:16 2019
-// Update Count     : 116
+// Last Modified On : Thu Nov 21 16:47:02 2019
+// Update Count     : 118
 //
 
@@ -163,5 +163,5 @@
 	abort_lastframe = kernel_abort_lastframe();
 	len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus getPid)
-	__cfaabi_dbg_bits_write( abort_text, len );
+	__cfaabi_dbg_write( abort_text, len );
 
 	if ( fmt ) {
@@ -171,8 +171,8 @@
 		len = vsnprintf( abort_text, abort_text_size, fmt, args );
 		va_end( args );
-		__cfaabi_dbg_bits_write( abort_text, len );
+		__cfaabi_dbg_write( abort_text, len );
 
 		if ( fmt[strlen( fmt ) - 1] != '\n' ) {		// add optional newline if missing at the end of the format text
-			__cfaabi_dbg_bits_write( "\n", 1 );
+			__cfaabi_dbg_write( "\n", 1 );
 		}
 	}
@@ -194,5 +194,5 @@
 	// find executable name
 	*index( messages[0], '(' ) = '\0';
-	__cfaabi_dbg_bits_print_nolock( "Stack back trace for: %s\n", messages[0]);
+	__cfaabi_bits_print_nolock( STDERR_FILENO, "Stack back trace for: %s\n", messages[0]);
 
 	for ( int i = Start; i < size - abort_lastframe && messages != NULL; i += 1 ) {
@@ -200,5 +200,5 @@
 
 		for ( char * p = messages[i]; *p; ++p ) {
-			//__cfaabi_dbg_bits_print_nolock( "X %s\n", p);
+			//__cfaabi_bits_print_nolock( "X %s\n", p);
 			// find parantheses and +offset
 			if ( *p == '(' ) {
@@ -220,7 +220,7 @@
 			*offset_end++ = '\0';
 
-			__cfaabi_dbg_bits_print_nolock( "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
+			__cfaabi_bits_print_nolock( STDERR_FILENO, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
 		} else {										// otherwise, print the whole line
-			__cfaabi_dbg_bits_print_nolock( "(%i) %s\n", frameNo, messages[i] );
+			__cfaabi_bits_print_nolock( STDERR_FILENO, "(%i) %s\n", frameNo, messages[i] );
 		}
 	}
Index: libcfa/src/stdlib.cfa
===================================================================
--- libcfa/src/stdlib.cfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/stdlib.cfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 17:10:29 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Oct 22 08:57:52 2019
-// Update Count     : 478
+// Last Modified On : Wed Nov 20 17:22:47 2019
+// Update Count     : 485
 //
 
@@ -30,50 +30,19 @@
 	T * alloc_set( T ptr[], size_t dim, char fill ) {	// realloc array with fill
 		size_t olen = malloc_usable_size( ptr );		// current allocation
-		char * nptr = (char *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
+		void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
 		size_t nlen = malloc_usable_size( nptr );		// new allocation
 		if ( nlen > olen ) {							// larger ?
-			memset( nptr + olen, (int)fill, nlen - olen ); // initialize added storage
+			memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
 		} // if
 		return (T *)nptr;
 	} // alloc_set
 
-	T * alloc_align( T ptr[], size_t align ) {			// aligned realloc array
-		char * nptr;
-		size_t alignment = malloc_alignment( ptr );
-		if ( align != alignment && (uintptr_t)ptr % align != 0 ) {
-			size_t olen = malloc_usable_size( ptr );	// current allocation
-			nptr = (char *)memalign( align, olen );
-			size_t nlen = malloc_usable_size( nptr );	// new allocation
-			size_t lnth = olen < nlen ? olen : nlen;	// min
-			memcpy( nptr, ptr, lnth );					// initialize storage
-			free( ptr );
-		} else {
-			nptr = (char *)ptr;
-		} // if
-		return (T *)nptr;
-	} // alloc_align
-
-	T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array
-		char * nptr;
-		size_t alignment = malloc_alignment( ptr );
-		if ( align != alignment ) {
-			size_t olen = malloc_usable_size( ptr );	// current allocation
-			nptr = (char *)memalign( align, dim * sizeof(T) );
-			size_t nlen = malloc_usable_size( nptr );	// new allocation
-			size_t lnth = olen < nlen ? olen : nlen;	// min
-			memcpy( nptr, ptr, lnth );					// initialize storage
-			free( ptr );
-		} else {
-			nptr = (char *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
-		} // if
-		return (T *)nptr;
-	} // alloc_align
-
 	T * alloc_align_set( T ptr[], size_t align, char fill ) { // aligned realloc with fill
 		size_t olen = malloc_usable_size( ptr );		// current allocation
-		char * nptr = alloc_align( ptr, align );
+		void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
+		// char * nptr = alloc_align( ptr, align );
 		size_t nlen = malloc_usable_size( nptr );		// new allocation
 		if ( nlen > olen ) {							// larger ?
-			memset( nptr + olen, (int)fill, nlen - olen ); // initialize added storage
+			memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
 		} // if
 		return (T *)nptr;
Index: libcfa/src/stdlib.hfa
===================================================================
--- libcfa/src/stdlib.hfa	(revision 7768b8df58110d321b6431c9d8728f39b7d92f86)
+++ libcfa/src/stdlib.hfa	(revision 30763fd9998ec2cdcee134d9878da68c14888f24)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 17:12:35 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Oct 20 22:57:33 2019
-// Update Count     : 390
+// Last Modified On : Fri Nov 22 15:13:14 2019
+// Update Count     : 399
 //
 
@@ -28,4 +28,6 @@
 } // extern "C"
 
+void * realloc( void * oaddr, size_t nalign, size_t size ); // CFA heap
+
 //---------------------------------------
 
@@ -50,6 +52,5 @@
 	} // calloc
 
-	T * realloc( T * ptr, size_t size ) {
-		if ( unlikely( ptr == 0 ) ) return malloc();
+	T * realloc( T * ptr, size_t size ) {				// CFA realloc, eliminate return-type cast
 		return (T *)(void *)realloc( (void *)ptr, size ); // C realloc
 	} // realloc
@@ -59,4 +60,8 @@
 	} // memalign
 
+	T * cmemalign( size_t align, size_t dim  ) {
+		return (T *)cmemalign( align, dim, sizeof(T) );	// CFA cmemalign
+	} // cmemalign
+
 	T * aligned_alloc( size_t align ) {
 		return (T *)aligned_alloc( align, sizeof(T) );	// C aligned_alloc
@@ -79,5 +84,5 @@
 
 	T * alloc( T ptr[], size_t dim ) {					// realloc
-		return realloc( ptr, dim * sizeof(T) );
+		return (T *)(void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
 	} // alloc
 
@@ -118,4 +123,12 @@
 	} // alloc_align
 
+	T * alloc_align( T ptr[], size_t align ) {			// aligned realloc array
+		return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
+	} // alloc_align
+
+	T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array
+		return (T *)(void *)realloc( (void *)ptr, align, dim * sizeof(T) ); // CFA realloc
+	} // alloc_align
+
 	T * alloc_align_set( size_t align, char fill ) {
 		return (T *)memset( (T *)alloc_align( align ), (int)fill, sizeof(T) ); // initialize with fill value
@@ -142,6 +155,4 @@
 
 forall( dtype T | sized(T) ) {
-	T * alloc_align( T ptr[], size_t align );			// realign
-	T * alloc_align( T ptr[], size_t align, size_t dim ); // aligned realloc array
 	T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); // aligned realloc array with fill
 } // distribution
