reallocarray(3bsd)
β¨ reallocarray β the manual page bestie π
okay so real talk: this is reallocarray(3bsd), from the LOCAL manual, and it's the glow-up your memory allocation game has been begging for. three little functions β reallocarray, recallocarray, freezero β and they're all about memory allocation and deallocation, but like, safely. no cap. π«Ά
πΈ NAME πΈ
reallocarray, recallocarray, freezero β memory allocation and deallocation π
π LIBRARY π
Utility functions from BSD systems (libbsd, -lbsd)
β¨ SYNOPSIS β¨
#include <stdlib.h>
(See libbsd(7) for include usage.)
void *
reallocarray(void *ptr, size_t nmemb, size_t size);
void *
recallocarray(void *ptr, size_t oldnmemb, size_t nmemb, size_t size);
void
freezero(void *ptr, size_t size);
ngl, that (See libbsd(7) for include usage.) line is literally part of the synopsis. it's giving "check the libbsd manpage for how to actually include this" π§
π DESCRIPTION π
so, reallocarray() was designed for the safe allocation of arrays, and it's basically realloc() but with β¨self-awarenessβ¨. instead of just one size, it operates on nmemb members of size size β and it checks for integer overflow in the calculation nmemb * size. that's the whole point. that's the moment. π
recallocarray() is the one you use for the allocation of memory holding sensitive data, and it guarantees that memory becoming unallocated is explicitly discarded β meaning cached free objects are cleared with explicit_bzero(3). so nothing lingers. no crumbs. π
recallocarray() is similar to reallocarray() except it ensures newly allocated memory is cleared similar to calloc(). and there are two cases, bestie:
- if
ptrisNULL, thenoldnmembis ignored and the call is equivalent tocalloc(). - if
ptris notNULL,oldnmembmust be a value such thatoldnmemb * sizeis the size of the earlier allocation that returnedptrβ otherwise the behavior is undefined. not "kinda weird", not "maybe fine" β undefined. π
freezero() is similar to the free() function except it ensures memory is explicitly discarded. the rules:
- if
ptrisNULL, no action occurs. (iconic, zero drama) - if
ptris notNULL, thesizeargument must be equal to or smaller than the size of the earlier allocation that returnedptr.
and freezero() guarantees the memory range starting at ptr with length size is discarded while deallocating the whole object originally allocated. so it wipes the part you care about, then frees the whole thing. slay. π₯
π RETURN VALUES π
reallocarray() and recallocarray() return a pointer to the allocated space if successful; otherwise, a null pointer is returned and errno is set to ENOMEM.
if multiplying nmemb and size results in integer overflow, reallocarray() and recallocarray() return NULL and set errno to ENOMEM. caught it. π
if ptr is not NULL and multiplying oldnmemb and size results in integer overflow, recallocarray() returns NULL and sets errno to EINVAL. (yes, different errno. read it again. π)
π IDIOMS π
okay this is the part where the manpage is basically your older sister going "bestie, please, I've seen things." consider calloc() or the extensions reallocarray() and recallocarray() when there is multiplication in the size argument of malloc() or realloc(). for example, avoid this common idiom as it may lead to integer overflow:
if ((p = malloc(num * size)) == NULL)
err(1, NULL);
a drop-in replacement is reallocarray():
if ((p = reallocarray(NULL, num, size)) == NULL)
err(1, NULL);
alternatively, calloc() may be used at the cost of initialization overhead. (you pay for the zeroing, basically π« )
when using realloc(), be careful to avoid the following idiom:
size += 50;
if ((p = realloc(p, size)) == NULL)
return (NULL);
do not adjust the variable describing how much memory has been allocated until the allocation has been successful. this can cause aberrant program behavior if the incorrect size value is used. in most cases, the above sample will also result in a leak of memory. as stated earlier, a return value of NULL indicates that the old object still remains allocated. better code looks like this:
newsize = size + 50;
if ((newp = realloc(p, newsize)) == NULL) {
free(p);
p = NULL;
size = 0;
return (NULL);
}
p = newp;
size = newsize;
as with malloc(), it is important to ensure the new size value will not overflow; i.e. avoid allocations like the following:
if ((newp = realloc(p, num * size)) == NULL) {
...
instead, use reallocarray():
if ((newp = reallocarray(p, num, size)) == NULL) {
...
calling realloc() with a NULL ptr is equivalent to calling malloc(). instead of this idiom:
if (p == NULL)
newp = malloc(newsize);
else
newp = realloc(p, newsize);
use the following:
newp = realloc(p, newsize);
the recallocarray() function should be used for resizing objects containing sensitive data like keys. to avoid leaking information, it guarantees memory is cleared before placing it on the internal free list. deallocation of such an object should be done by calling freezero(). π
π SEE ALSO π
malloc(3), calloc(3), alloca(3)
π¦ HISTORY π¦
the reallocarray() function appeared in OpenBSD 5.6, DragonFly 5.5 and glibc 2.26.
the recallocarray() function appeared in OpenBSD 6.1 and DragonFly 5.5.
the freezero() function appeared in OpenBSD 6.2 and DragonFly 5.5.
and that's the whole page, bestie π«Ά this one's from Debian, dated September 14, 2019, and it lives at reallocarray(3bsd). now go forth and never write malloc(num * size) again. I'm watching. πβ¨
π¦ where this page comes from
- alpine 3.22: libbsd-doc 0.12.2-r0 Β· BSD-3-Clause
- alpine 3.23: libbsd-doc 0.12.2-r0 Β· BSD-3-Clause
- alpine 3.24: libbsd-doc 0.12.2-r0 Β· BSD-3-Clause
- arch rolling: libbsd 0.12.2-2 Β· custom
- debian trixie: libbsd-dev 0.12.2-2
- epel 10: libbsd-devel 0.12.2-4.el10_0 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- epel 9: libbsd-devel 0.12.2-1.el9 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- fedora 43: libbsd-devel 0.12.2-6.fc43 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- fedora 43: libbsd-devel 0.12.2-6.fc43 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- fedora 44: libbsd-devel 0.12.2-7.fc44 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- fedora 44: libbsd-devel 0.12.2-7.fc44 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- nixos 26.05: libbsd 0.12.2
- nixpkgs unstable: libbsd 0.12.2
- ubuntu noble: libbsd-dev 0.12.1-1build1
- ubuntu noble: libbsd-dev 0.12.1-1build1.1
- ubuntu questing: libbsd-dev 0.12.2-2build1
- ubuntu resolute: libbsd-dev 0.12.2-2build2
- ubuntu stonking: libbsd-dev 0.12.2-3
- Copyright (c) 1980, 1991, 1993 The Regents of the University of California. All rights reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms