17.4.3 Memory Allocation Functions and Convenience Macros

The API provides a number of memory allocation functions for allocating memory that can be passed to gawk, as well as a number of convenience macros. This subsection presents them all as function prototypes, in the way that extension code would use them:

void *gawk_malloc(size_t size);

Call the correct version of malloc() to allocate storage that may be passed to gawk.

void *gawk_calloc(size_t nmemb, size_t size);

Call the correct version of calloc() to allocate storage that may be passed to gawk.

void *gawk_realloc(void *ptr, size_t size);

Call the correct version of realloc() to allocate storage that may be passed to gawk.

void gawk_free(void *ptr);

Call the correct version of free() to release storage that was allocated with gawk_malloc(), gawk_calloc(), or gawk_realloc().

The API has to provide these functions because it is possible for an extension to be compiled and linked against a different version of the C library than was used for the gawk executable.107 If gawk were to use its version of free() when the memory came from an unrelated version of malloc(), unexpected behavior would likely result.

Three convenience macros may be used for allocating storage from gawk_malloc(), gawk_calloc, and gawk_realloc(). If the allocation fails, they cause gawk to exit with a fatal error message. They should be used as if they were procedure calls that do not return a value:

#define emalloc(pointer, type, size, message) …

The arguments to this macro are as follows:

pointer

The pointer variable to point at the allocated storage.

type

The type of the pointer variable. This is used to create a cast for the call to gawk_malloc().

size

The total number of bytes to be allocated.

message

A message to be prefixed to the fatal error message. Typically this is the name of the function using the macro.

For example, you might allocate a string value like so:

awk_value_t result;
char *message;
const char greet[] = "Don't Panic!";

emalloc(message, char *, sizeof(greet), "myfunc");
strcpy(message, greet);
make_malloced_string(message, strlen(message), & result);


#define ezalloc(pointer, type, size, message) …

This is like emalloc(), but it calls gawk_calloc() instead of gawk_malloc(). The arguments are the same as for the emalloc() macro, but this macro guarantees that the memory returned is initialized to zero.

#define erealloc(pointer, type, size, message) …

This is like emalloc(), but it calls gawk_realloc() instead of gawk_malloc(). The arguments are the same as for the emalloc() macro.

Two additional functions allocate MPFR and GMP objects for use by extension functions that need to create and then return such values.

NOTE: These functions are obsolete. Extension functions that need local MPFR and GMP values should simply allocate them on the stack and clear them, as any other code would.

The functions are:

void *get_mpfr_ptr();

Allocate and initialize an MPFR object and return a pointer to it. If the allocation fails, gawk exits with a fatal “out of memory” error. If gawk was compiled without MPFR support, calling this function causes a fatal error.

void *get_mpz_ptr();

Allocate and initialize a GMP object and return a pointer to it. If the allocation fails, gawk exits with a fatal “out of memory” error. If gawk was compiled without MPFR support, calling this function causes a fatal error.

Both of these functions return ‘void *’, since the gawkapi.h header file should not have dependency upon <mpfr.h> (and <gmp.h>, which is included from <mpfr.h>). The actual return values are of types mpfr_ptr and mpz_ptr respectively, and you should cast the return values appropriately before assigning the results to variables of the correct types.

The memory allocated by these functions should be freed with gawk_free().


Footnotes

(107)

This is more common on MS-Windows systems, but it can happen on Unix-like systems as well.