L'implémentation de la fonction malloc() est spécifique au système et à la bibliothèque. L'une des choses que de nombreuses implémentations d'allocation de mémoire doivent gérer est la fragmentation de la mémoire.
Le code de question alloue 4 octets. Afin de minimiser la fragmentation de la mémoire, de nombreux systèmes allouent réellement plus de 4; peut-être un minimum de 16 octets. Cela permet à la fois de satisfaire la requête malloc (4) et de conserver des fragments de mémoire (une fois la mémoire libérée) à une taille minimale de 16 octets. Par conséquent, un "pool de fragments de mémoire" de 16 fragments d'octets peut être utilisé pour satisfaire une requête malloc() de 1 à 16 octets. De nombreux systèmes de gestion de mémoire maintiennent des "pools de fragments de mémoire" de 16, 32, 64, 128, (etc) octets chacun. Par exemple, si un appel de malloc (44) est effectué, un fragment de mémoire du pool de 64 octets peut satisfaire la requête.
Sur certains systèmes, il est possible de déterminer la taille réelle du fragment de mémoire renvoyé par malloc(). Sur un système Linux, la fonction malloc_usable_size() exécute cette fonction. Les systèmes OS X peuvent utiliser malloc_size().
Le comportement indéfini est indéfini. Il n'y a aucune garantie qu'il soit détecté du tout. – Deduplicator
C est une langue de bas niveau. Il vous permettra heureusement de vous tirer dans le pied tout ce que vous aimez, et peut ou ne peut pas vous avertir. –
"Ne devrais-je pas avoir une erreur de segmentation?" Non. C ne vous spécifie pas de faute de seg_. Cela peut arriver. C'est UB. D'autres langues peuvent spécifier qu'une erreur seg doit se produire. Cela nécessite souvent du code ou des performances supplémentaires. Si [roues de formation] (https://en.wikipedia.org/wiki/Training_wheels) sont nécessaires, envisagez d'autres langues. – chux