GNU Astronomy Utilities



12.3.4 Pointers (pointer.h)

Pointers play an important role in the C programming language. As the name suggests, they point to a byte in memory (like an address in a city). The C programming language gives you complete freedom in how to use the byte (and the bytes that follow it). Pointers are thus a very powerful feature of C. However, as the saying goes: “With great power comes great responsibility”, so they must be approached with care. The functions in this header are not very complex, they are just wrappers over some basic pointer functionality regarding pointer arithmetic and allocation (in memory or HDD/SSD).

Function:
void *
gal_pointer_increment (void *pointer, size_t increment, uint8_t type)

Return a pointer to an element that is increment elements ahead of pointer, assuming each element has type of type. For the type codes, see Library data types (type.h).

When working with the array elements of gal_data_t, we are actually dealing with void * pointers. However, pointer arithmetic does not apply to void *, because the system does not know how many bytes there are in each element to increment the pointer respectively. This function will use the given type to calculate where the incremented element is located in memory.

Function:
size_t
gal_pointer_num_between (void *earlier, void *later, uint8_t type)

Return the number of elements (in the given type) between earlier and later. For the type codes, see Library data types (type.h)).

Function:
void *
gal_pointer_allocate (uint8_t type, size_t size, int clear, const char *funcname, const char *varname)

Allocate an array of type type with size elements in RAM (for the type codes, see Library data types (type.h)). If clear!=0, then the allocated space is set to zero (cleared).

This is effectively just a wrapper around C’s malloc or calloc functions but takes Gnuastro’s integer type codes and will also abort with a clear error if there the allocation was not successful. The number of allocated bytes is the value given to size that is multiplied by the returned value of gal_type_sizeof for the given type. So if you want to allocate space for an array of strings you should pass the type GAL_TYPE_STRING. Otherwise, if you just want space for one string (for example, 6 bytes for hello, including the string-termination character), you should set the type GAL_TYPE_UINT8.

When space cannot be allocated, this function will abort the program with a message containing the reason for the failure. funcname (name of the function calling this function) and varname (name of variable that needs this space) will be used in this error message if they are not NULL. In most modern compilers, you can use the generic __func__ variable for funcname. In this way, you do not have to manually copy and paste the function name or worry about it changing later (__func__ was standardized in C99). To use this function effectively and avoid memory leaks, make sure to free the allocated array after you are done with it. Also, be mindful of any functions that make use of this function as they should also free any allocated arrays to maintain memory management and prevent issues with the system.

Function:
void *
gal_pointer_allocate_ram_or_mmap (uint8_t type, size_t size, int clear, size_t minmapsize, char **mmapname, int quietmmap, const char *funcname, const char *varname)

Allocate the given space either in RAM or in a memory-mapped file. This function is just a high-level wrapper to gal_pointer_allocate (to allocate in RAM) or gal_pointer_mmap_allocate (to use a memory-mapped file). For more on memory management in Gnuastro, please see Memory management. The various arguments are more fully explained in the two functions above.

Function:
void *
gal_pointer_mmap_allocate (size_t size, uint8_t type, int clear, char **mmapname, int allocfailed)

Allocate the necessary space to keep size elements of type type in HDD/SSD (a file, not in RAM). For the type codes, see Library data types (type.h). If clear!=0, then the allocated space will also be cleared. The allocation is done using C’s mmap function. The name of the file containing the allocated space is an allocated string that will be put in *mmapname.

Note that the kernel does not allow an infinite number of memory mappings to files. So it is not recommended to use this function with every allocation. The best-case scenario to use this function is for arrays that are very large and can fill up the RAM. Keep the smaller arrays in RAM, which is faster and can have a (theoretically) unlimited number of allocations.

When you are done with the dataset and do not need it anymore, do not use free (the dataset is not in RAM). Just delete the file (and the allocated space for the filename) with the commands below, or simply use gal_pointer_mmap_free.

remove(mmapname);
free(mmapname);

If allocfailed!=0 and the memory mapping attempt fails, the warning message will say something like this (assuming you have tried something like malloc before calling this function): even though there was enough space in RAM, the previous attempts at allocation in RAM failed, so we tried memory mapping, but that also failed.

Function:
void
gal_pointer_mmap_free (char **mmapname, int quietmmap)

“Free” (actually delete) the memory-mapped file that is named *mmapname, then free the string. If quietmmap is non-zero, then a warning will be printed for the user to know that the given file has been deleted.