Resource management with CIF API

The core CIF API, being written in C, leaves basic responsibility for resource management in the hands of the application programmer. Nevertheless, the API is designed to make the resource management burden as light as reasonably possible. What follows is a discussion of many of the considerations and specific API features that relate to resource management.

Resource management basics

For the most part, CIF API objects are created dynamically via functions having _create in their names (cif_create_block(), for example). Each object type for which there is a creation function has one or more functions for releasing that object and all its internal state:

Use of the type-specific resource release functions ensures that all internal state is correctly released. Application code must not pass CIF API objects to the C library's free() function, except as may be explicitly described elsewhere in the API documentation.

Except where otherwise specified, CIF API functions that return a pointer to the caller via a pointer pointer (as object creation functions in particular do) thereby assign responsibility for the returned pointer to the calling function. More generally, any function that allocates an object directly or indirectly bears initial responsibility for releasing that object. It must ensure the object is released before it returns, or else it must pass responsibility for doing so to another context (typically the caller's). Note, too, that API functions that accept a pointer pointer argument vary with respect to what they do with the value, if any, that the argument initially points to. Many of them simply overwrite it, which will result in a memory leak if the caller passes a pointer to the only pointer to a live object.

Except where otherwise specified (such as for the cif_*_free() and cif_*_destroy() functions), passing a pointer as a CIF API function argument does not transfer responsibility for the pointed-to object to the called function. Furthermore, API functions do not create aliases to their pointer arguments that would make it unsafe for the responsible function to clean them up at its sole discretion. Where necessary, API functions copy objects in order to avoid creating aliases to them. These characteristics are intended to minimize confusion about whether application code can or should release any particular CIF API object.

Some API functions accept or return general objects such as arrays or Unicode strings. For the most part, the same rules apply to such objects as to CIF API objects, but the API does not provide resource management functions for such objects. See specific function documentation for details. With respect to arrays in particular, consult function docs for information about responsibility for array elements, as distinguished from responsibility for the array itself.

It should be borne in mind that CIF API handle objects, such as those of types cif_container_tp and cif_loop_tp , are separate resources from the corresponding parts of managed CIFs. At any given time, for any given part of a managed CIF, there may be any number -- including zero -- of extant, valid handles. New handles can be obtained for existing managed CIF pieces, and handles can be released without affecting the underlying managed CIF. Destroying the underlying managed piece invalidates all outstanding handles, but releases only the handle, if any, by which the destruction was performed.

Exceptions and special cases

The CIF API provides a handful of functions having resource management relevance that do not fit the general pattern:

 All Data Structures Variables

Copyright 2014, 2015 John C. Bollinger