(_type **) tarray_alloc(m1, n1, m2, n2, _type) (_type *) tvector_alloc(n1, n2, _type) (void ***) parray_alloc(m1, n1, m2, n2) (void **) pvector_alloc(n1, n2) (char **) carray_alloc(m1, n1, m2, n2) (char *) cvector_alloc(n1, n2) (short **) sarray_alloc(m1, n1, m2, n2) (short *) svector_alloc(n1, n2) (int **) iarray_alloc(m1, n1, m2, n2) (int *) ivector_alloc(n1, n2) (float **) farray_alloc(m1, n1, m2, n2) (float *) fvector_alloc(n1, n2) (double **) darray_alloc(m1, n1, m2, n2) (double *) dvector_alloc(n1, n2) (Complex **) zarray_alloc(_m1, _n1, _m2, _n2) (Complex *) zvector_alloc(_n1, _n2)There are also corresponding copy, data zero and free functions. The free function macros are written not only to free the structure but also set the corresponding pointer to NULL so that any future attempt to free the same vector or array can be trapped and reported via a call to error(), with the message
warning : attempt to free NULL pointer in nvector_free()This simple expedient will trap half the causes of potential memory overwrites during software development 6.1. Attempts to free vectors defined with an inconsistent starting location are also trapped,, with the message
non_fatal : attempt to free re-defined vector in nvector_free()This can be caused either by overwriting or simply specifying the wrong starting location.
Two points of note however, data structures generated with these macros must be freed with the corresponding free macros and not free() so that any specified offsets in the data are handelled correctly. Also, these dynamic structures should not be used as a component in a new data structure or hung off property lists if you intend to make direct use of the serialise process. The Matrix and Vector data structures should be used for this purpose.