3.1 KiB
Memory allocation and ownership
Any library needs to take data from users, and then return data to
users. With some types this is simple - integer parameters and return
types are trivial. But with more complex data types, things are more
complicated. Even something seemingly simple, like a C string, requires
discipline: we cannot simple return an allocated hunk of memory for
callers to free
, since some systems have multiple allocators and users
cannot necessarily reason about the allocator used and which corresponding
deallocation function to call to free the memory.
Objects
Most types in libgit2 are "opaque" types, which we treat as "objects" (even
though C is "not an object oriented language"). You may create an object -
for example, with git_odb_new
, or libgit2 may return you an object as an
"out" parameter - for example, with git_repository_open
. With any of
these objects, you should call their corresponding _free
function (for
example, git_odb_free
or git_repository_free
) when you are done using
them.
Structures
libgit2 will often take input as structures (for example, options
structures like git_merge_options
). Rarely, libgit2 will return data in
a structure. This is typically used for simpler data types, like git_buf
and git_strarray
. Users should allocate the structure themselves (either
on the stack or the heap) and pass a pointer to it. Since libgit2 does not
allocate the structure itself, only the data inside of it, the deallocation
functions are suffixed with _dispose
instead of _free
, since they only
free the data inside the structure.
Strings or continuous memory buffers (git_buf
)
libgit2 typically takes NUL-terminated strings ("C strings") with a
const char *
, and typically takes raw data with a const char *
and a
corresponding size_t
for its size. libgit2 typically returns strings
or raw data in a git_buf
structure. The given data buffer will always be
NUL terminated (even if it contains binary data) and the size
member will
always contain the size (in bytes) of the contents of the pointer (excluding
the NUL terminator).
In other words, if a git_buf
contains the string foo
then the memory
buffer will be { f
, o
, o
, \0
} and the size will be 3
.
Callers must initialize the buffer with GIT_BUF_INIT
(or by setting
all the members to 0
) when it is created, before passing a pointer
to the buffer to libgit2 for the first time.
Subsequent calls to libgit2 APIs that take a buffer can re-use a buffer that was previously used. The buffer will be cleared and grown to accommodate the new contents (if necessary). The new data will written into the buffer, overwriting the previous contents. This allows callers to reduce the number of allocations performed by the library.
Callers must call git_buf_dispose
when they have finished.
Note that the deprecated git_diff_format_email
API does not follow
this behavior; subsequent calls will concatenate data to the buffer
instead of rewriting it. Users should move to the new git_email
APIs that follow the git_buf
standards.