malloc(3)

NAAM
malloc, free, calloc, realloc - reserveren en vrijmaken van dynamisch geheugen

BIBLIOTHEEK
Standaard C bibliotheek (libc, -lc)

SAMENVATTING
#include <stdlib.h>

void *malloc(size_t size);
void free(void *_Nullable p);
void *calloc(size_t n, size_t size);
void *realloc(void *_Nullable p, size_t size);
void *reallocarray(void *_Nullable p, size_t n, size_t size);

    Feature Test Macro Requirements voor glibc (zie feature_test_macros(7)):

reallocarray():
    Sinds glibc 2.29:
        _DEFAULT_SOURCE
    Glibc 2.28 en eerder:
        _GNU_SOURCE

BESCHRIJVING

  malloc()
De malloc() functie reserveert grootte bytes geheugen en geeft een wijzer naar het gereserveerde geheugen terug. Het geheugen wordt niet geinitialiseerd. Als grootte gelijk is aan 0, dan retourneert malloc() een unieke wijzer waarde die later kan worden mee gegeven aan free(). (Zie "Niet overdraagbaar gebrag" voor overdraagbaarheids onderwerpen)

  free()
De free() functie geeft de geheugen-ruimte waar wzr naar wijst vrij, die moet zijn teruggegeven door een eerdere aanroep naar malloc() of gerelateerde functies.Anders, of als wzr al eerder werd vrijgegeven, ontstaat ongedefinieerd gedrag. Als wzr gelijk is aan NULL wordt niks uitgevoerd.

  calloc()
De calloc() functie reserveert grootte bytes geheugen voor een array en geeft een wijzer naar het gereserveerde geheugen terug. Het geheugen wordt met nul geïnitialiseerd. Als n of grootte gelijk is aan 0, dan retourneert calloc() een unieke wijzer waarde die later succesvol kan worden mee gegeven aan free().

Als de vermenigvuldiging van n en grootte zou resulteren in het overlopen van een geheel getal, dan geeft calloc() een fout terug. In tegenstelling daarmee, zou het overlopen van een geheel getal niet gedetecteerd worden in de volgende aanroep van malloc(), met als resultaat dat een geheugen blok van een niet correct grootte zou worden toegewezen:

    malloc(n * grootte);

  realloc()
 e realloc() functie verandert de grootte van het geheugen-blok waar wzr naar wijst in grootte bytes. De inhoud zal onveranderd blijven in het gebied dat begint bij het geheugen gebied tot aan het minimum van de oude en nieuwe grootte. Als de nieuwe grootte groter is dan de oude dan wordt het toegevoegde geheugen niet geïnitialiseerd.

Als wzr NULL is, dan is de aanroep equivalent aan malloc(grootte), voor alle waarden van grootte.

Als grootte gelijk is aan nul, en wzr is niet NULL, dan is de aanroep equivalent aan free(ptr) (echter zie "Niet overdraagbaar gedrag" voor overdraagbaarheid onderwerpen).

Behalve als wzr NULL is, zou het moeten zijn teruggegeven door een eerdere aanroep van malloc() of gerelateerde functies. Als het gebied waar naar gewezen wordt verplaatst werd dan wordt een free(wzr) uitgevoerd.

  reallocarray()
De reallocarray() functie verandert de grootte van het blok (verplaatst dit mogelijk) aangewezen door ptr om groot genoeg te zijn voor een array van n elementen, elk met een grootte van grootte bytes. Dit is equivalent aan de aanroep:

    realloc(ptr, n * grootte);

Echter, anders dan de realloc() aanroep, reallocarray() faalt veilig in het geval dat de multiplicatie zou overlopen. Als zo een overloop optreed, reallocarray() retourneert een NULL.

EIND WAARDE
De malloc, calloc(), realloc() en reallocarry() functies retourneren een wijzer naar het gereserveerde geheugen, dat geschikt is opgelijnd voor elk ingebouwd type dat past in de beschikbare ruimte. Bij een fout, retourneren deze functies NULL en zetten errno. Proberen te reserveren van meer dan PTRDIFF_MAX bytes wordt gezien als een fout, omdat een object van deze grootte later kan leiden tot overlopen bij het aftrekken van wijzers.

De free() functie geeft geen waarde terug, en behoudt errno.

De realloc() en reallocarray() functies retourneren NULL als wzr niet NULL en de gevraagde grootte nul is; dit wordt niet beschouwd als een fout. (Zie "Niet overdraagbaar gedrag" voor overdraagbaarheid onderwerpen). De teruggegeven wijzer kan dezelfde zijn als wzr als de reservering niet was verplaatst (b.v. er was ruimte om de ruimte uit te breiden), of verschillend van wzr als de reservering was verplaatst naar een nieuw adres. Als deze functies falen, dan wordt het originele blok niet aangetast; het wordt niet verplaatst of vrij gegeven.

FOUTEN
calloc(), malloc(), realloc(), en reallocarray() kunnen falen met de volgende fout:

ENOMEM
    Geen geheugen meer. Mogelijk, het programma bereikte de RLIMIT_AS of RLIMIT_DATA limiet beschreven in getrlimit(2). Een andere reden zou kunnen zijn dat het aantal mappings die aangemaakt worden door het aanroepende proces de limiet zoals aangegeven door /proc/sys/vm/max_map_count hebben overschreden.

ATTRIBUTEN
Voor een uitleg van de termen zoals gebruikt in deze sectie, zie attributen(7).
Interface | Attribuut | Waarde
malloc(), free(), calloc(), realloc() | Thread veilig | MT-Safe

STANDAARDEN

malloc()
free()
calloc()
realloc()
    C23, POSIX.1-2024.

reallocarray()
    POSIX.1-2024.

  realloc(p, 0)
Het gedrag van realloc(p, 0) in glibc voldoet niet aan enig van C99, C11, POSIX.1-2001, POSIX.1-2004, POSIX.1-2008, POSIX.1-2013, POSIX.1-2017, or POSIX.1-2024. De C17 specificatie werd veranderd om het te laten voldoen, maar deze specificatie maakte het onmogelijk code te schrijven die betrouwbaar bepaald of de input wijzer vrij gegeven wordt na realloc(p, 0), en C23 veranderde het nogmaals dor dit tot ongedefinieerd gedrag te verklaren, daarbij bekennende dat de C17 specificatie al breed genoeg was en dat ongedefinieerd gedrag niet slechter was.

reallocarray() lijdt aan dezelfde dingen in glibc.

musl libc en de BSDs voldoen aan alle versies van ISO C en POSIX.1.

gnulib voorziet in de realloc-posix module, die voorziet in de omwikkelfuncties realloc() en reallocarray() die voldoen aan alle versies van ISO C en POSIX.1.

Er bestaat een voorstel om het BSD gedrag te standaardiseren: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3621.txt.

HISTORIE

malloc()
free()
calloc()
realloc()
    POSIX.1-2001, C89.

reallocarray()
    glibc 2.26. OpenBSD 5.6, FreeBSD 11.0.

malloc() en gerelateerde functies verwerpen groottes groter dan PTRDIFF_MAX vanaf glibc 2.30.

free() behoudt errno vanaf glibc 2.33.

  realloc(p, 0)
C89 was ambigu in de specificatie van realloc(p, 0). C99 loste dit deels op.

De originele implementatie in glibc zou hebben voldaan aan C99. Hoewel, en ironisch genoeg, terwijl te trachten te voldoen aan C99 vóór de standaard werd vrijgegeven, veranderde glibc het gedrag in glibc 2.1.1 naar iets dat uiteindelijk niet voldeed aan de finale C99 specificatie (hoewel hierover gedebatteerd kan worden omdat de verwoording in de standaard zelf tegenstrijdig lijkt).

OPMERKINGEN
Standaard volgt, Linux een optimistische geheugen toewijzing strategie. Dit betekent dat wanneer malloc() een niet-NULL terug geeft returns dat er nog geen garantie is dat het geheugen ook daadwerkelijk beschikbaar is. In het geval dat blijkt dat het systeem geen vrij geheugen meer heeft, dan worden een of meer processen vernietigd door de OOM vernietiger. Voor meer informatie, zie de beschrijving van /proc/sys/vm/overcommit_memory en /proc/sys/vm/oom_adj in proc(5), en het Linux kernel bron code bestand and the Linux Documentation/vm/overcommit-accounting.rst.

Normaliter kent malloc() geheugen toe van de heap en past de grootte van de heap aan zoals vereist, gebruikmakende van sbrk(2). Bij het toekennen van blokken geheugen groter dan MMAP_THRESHOLD bytes kent de glibc malloc() implementatie het geheugen toe als een private anoniem tabel met behulp van mmap(2). MMAP_THRESHOLD is standaard 128 kB, maar is instelbaar m.b.v. mallopt(3). Voor Linux 4.7 werden toekenningen gedaan met mmap(2) niet beïnvloed door de RLIMIT_DATA bron limiet; vanaf Linux 4.7, wordt deze limiet afgedwongen voor toekenningen gedaan met mmap(2).

Om corruptie in multi-threaded applicaties te vermijden worden semaforen intern gebruikt om geheugen-management data structuren die deze functies gebruiken te beschermen. In een multi-threaded application waarin threads gelijktijdig geheugen toekennen en vrijgeven kan er een botsing zijn voor deze semaforen. Om schaalbaar geheugen toekenning te kunnen afhandelen in een multi-threaded applicatie creëert glibc additionele memory allocation areas zodra semafoor botsingen worden gedetecteerd. Elk gebied is een grote geheugen regio die intern toegekend wordt door het systeem (m.b.v. brk(2) of mmap(2)), en bewaakt met zijn eigen semaforen.

Als uw programma een privé geheugen reservering gebruikt, dan dient het dit te doen door vervangen van malloc(), free(), calloc(), en realloc(). De vervangings functies moeten het gedocumenteerde glibc gedrag, inclusief errno afhandeling, grootte-nul toekenning, en controle van overloop implementeren, anders kunnen bibliotheek functies crashen of niet correct werken. Bij voorbeeld, als de vervanging van free() errno niet behoudt dan kunnen ogenschijnlijk niet gerelateerde bibliotheek functie falen zonder een geldige reden in errno. Privé geheugen reserveringen kunnen ook andere glibc functies vervangen; zie "Vervangen van malloc" in de glibc handleiding voor details.

Crashes in bij het toewijzen van geheugen zijn bijna altijd gerelateerd aan corruptie van de heap, zoals overlopen van een toegekend gebied or twee keer vrij geven van dezelfde wijzer.

De malloc() implementatie is aanpasbaar via omgeving variabelen; zie mallopt(3) voor details.

  Niet overdraagbaar gedrag
Het gedrag van deze functies wanneer de gevraagde grootte nul is, is glibc afhankelijk; andere implementaties kunnen NULL teruggeven zonder errno te zetten. Overdraagbare POSIX programma´s moeten dit gedrag tolereren. Zie realloc(3p).

POSIX vereist dat geheugen toewijzingen op errno worden gezet bij een fout. Hoewel de C standaard dat niet vereist, en applicaties die overgezet worden naar niet-POSIX platformen moeten hier niet van uit gaan.

Overdraagbare programma´s moeten geen privé geheugen reserveringen gebruiken, omdat POSIX en de C standaard geen vervanging van malloc(), free(), calloc(), en realloc() toestaan.

BUGS
Programmeurs zouden natuurlijk verwachten bij inductie dat realloc(p, size) consistent is met free(p) en malloc(size), omdat dat het algemene gedrag is. Dit wordt niet expliciet vereist in POSIX.1-2024 of C11, maar alle implementaties zijn hiermee consistent.

De glibc implementatie van realloc() is niet consistent met deze, met de consequentie dat het gevaarlijk is om realloc(p, 0) in glibc aan te roepen.

Een triviale tijdelijke oplossing voor glibc is door realloc(p, size?size:1) aan te roepen.

De tijdelijke oplossing voor reallocarray() in glibc — die dezelfde bug heeft als bug— zou reallocarray(p, n?n:1, size?size:1) zijn.

VOORBEELDEN
    #include <err.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #define MALLOCARRAY(n, type)  ((type *) my_mallocarray(n, sizeof(type)))
    #define MALLOC(type)          MALLOCARRAY(1, type)

    static inline void *my_mallocarray(size_t n, size_t size);

    int
    main(void)
    {
        char  *p;

        p = MALLOCARRAY(32, char);
        if (p == NULL)
            err(EXIT_FAILURE, "malloc");

        strlcpy(p, "foo", 32);
        puts(p);
    }

    static inline void *
    my_mallocarray(size_t nmemb, size_t size)
    {
        return reallocarray(NULL, nmemb, size);
    }

ZIE OOK
valgrind(1), brk(2), mmap(2), alloca(3), malloc_get_state(3), malloc_info(3), malloc_trim(3), malloc_usable_size(3), mallopt(3), mcheck(3), mtrace(3), posix_memalign(3)

Voor details over de GNU C library implementatie, zie https://sourceware.org/glibc/wiki/MallocInternals.

VERTALING
De Nederlandse vertaling van deze handleiding is geschreven door Jos Boersema <joshb@xs4all.nl>, Mario Blättermann <mario.blaettermann@gmail.com> en Luc Castermans <luc.castermans@gmail.com>

Deze vertaling is vrije documentatie; lees de GNU General Public License Version 3 (https://www.gnu.org/licenses/gpl-3.0.html) of later over de Copyright-voorwaarden. Er is geen AANSPRAKELIJKHEID.

Indien U fouten in de vertaling van deze handleiding zou vinden, stuur een e-mail naar debian-l10n-dutch@lists.debian.org.