Skip to content

Shallow Copies

Gustav Louw edited this page Dec 29, 2020 · 6 revisions

CTL passes all types T by value to various container functions, giving an easy to use syntax for modifying a container with a single line:

vec_int_push_back(&a, 1); 

The following is valid:

int value = 1;
vec_int_push_back(&a, value); 

But types with memory ownership, functions consume (shallow copy) types with memory ownership:

typedef struct { int* x; } digit;

digit
digit_init(int value)
{
    digit d = { malloc(sizeof(int)) };
    d.x = value;
    return d;
}
digit d = digit_init(42);
vec_digit_push_back(&a, d); 

digit d is copied by value (shallow copied) and inserted as a new element into the vec container. A free on d after its insertion will cause a heap use after free runtime fault, or potentially a double free runtime fault. Syntax vec_int_push_back(&a, 1), where the function call and type resides on the same line, aids in preventing heap use after free runtime faults, or double free runtime faults with memory ownership types, by conjoining the construction of the type with its container call, as below:

vec_digit_push_back(&a, digit_init(42));

All CTL functions are marked as static inline. Given gcc compiles with optimization settings -O1 or higher, superfluous copies by value will largely be eliminated. In summary, functions with type T (see below) consume their type, and are best used with the single line syntax outlined above:

static inline void
JOIN(A, resize)(A* self, size_t size, T value);

static inline void
JOIN(A, assign)(A* self, size_t size, T value);

static inline void
JOIN(A, push_back)(A* self, T value);

static inline void
JOIN(A, push_front)(A* self, T value);
Clone this wiki locally