Memory Allocation concerns
Memory allocation is probably the number one pitfall when writing
Clipper 5.0 user defined functions in C. This is due to the fact
that with the introduction of Clipper 5.0, run-time memory allocation
is accomplished via the Clipper VMM (Virtual Memory Manager.)1 In
past versions of Clipper, when allocating memory from within C, the
use of the Clipper Extend System memory allocation functions was
recommended. With the inclusion of VMM in Clipper 5.x memory
allocation via the Clipper extend system it is an absolute must. It
is equally important to make absolutely sure that you free the memory
you have allocated.
Allocating memory with the Extend System
The Extend System functions for memory allocation are _xalloc
and _xgrab. To allocate memory from C make a call to either
_xalloc and _xgrab which returns a pointer if successful.
The difference between the two is the way they handle an
error: _xalloc returns a Null pointer to the C routine and
_xgrab triggers a Clipper error. Avoid C Library routines
that allocate memory. Many C Library functions automatically
allocate memory using the C library's memory allocation
routines. This automatic memory allocation must be avoided.
Care must be taken when using library routines from the
following categories.2
Memory Allocation routines
Based on the statement that all memory must be allocated by
the Clipper extend system, is should be no surprise that C
memory allocation routines can not be used. This includes
alloca, calloc, malloc, along with their companion memory
freeing functions.
String manipulation routines
Most string manipulation functions are passed both the source
and target strings. Because of this, string manipulation
functions are generally quite easy to adapt to clipper use.
Simply allocate the source and target buffers using an extend
function, and pass them to the string function as normal.
Stream (buffered) I/O
By default, Stream I/O routines (i.e.: fopen(), fclose(),
fread(), fwrite(), ... ) automatically allocate memory for a
stream buffer. They should be avoided, and the Low Level
File I/O routines (i.e.: open(), close(), read(), write(),
... ) should be used instead. Also, printf() (and scanf() )
are stream I/O routines and must be avoided. Fortunately,
cprintf() and sprintf() (along with cscanf() and sscanf())
will work. The following shows how to substitute these
functions for printf():
Instead of: printf( "Hello, world.\n" )
use: cprintf( "Hello, world.\r\n" )
// uses raw mode - \n is CR only
or: sprintf( stdout, "Hello, world.\n" )
// stdout is defined in stdio.h