strdup(3)
Fonction de la bibliothèque C
Alloue avec malloc une copie d'une chaîne et renvoie son adresse, ou NULL. Dans la norme C depuis C23 ; la copie est à libérer avec free.
#include <string.h>
char *strdup(const char *s);Description
strdup crée une copie de la chaîne s dans un bloc alloué comme par malloc(3), et renvoie l'adresse de ce bloc. Elle fait en un appel ce qu'on écrirait sinon en trois lignes : mesurer avec strlen(3), allouer strlen(s) + 1 octets, copier avec strcpy(3). La copie est indépendante de l'original : modifier l'un ne touche pas l'autre, et elle survit à la fonction qui l'a créée.
Longtemps, strdup n'a existé que dans POSIX, pas dans la norme C. C23 l'a ajoutée à <string.h>, avec sa cousine strndup, qui copie au plus n caractères.
Valeur de retour
L'adresse de la copie, à rendre avec free(3) quand tu n'en as plus besoin. Si l'allocation échoue, strdup renvoie NULL et errno indique l'erreur, comme pour malloc.
Pièges
Chaque strdup est un malloc caché. Une copie jamais libérée est une fuite, que Valgrind classe « definitely lost » avec la pile d'appels malloc, strdup, puis la ligne de ton code qui a appelé strdup.
Teste le retour avant d'utiliser la copie : sur NULL, le premier accès est un comportement indéfini.
strdup(NULL) est lui aussi un comportement indéfini, puisque s doit désigner une chaîne.
En mode strict, la glibc ne déclare strdup que si la norme demandée la contient, ou si une macro POSIX la réclame. En -std=c17, sans macro POSIX, l'en-tête ne la déclare pas, et GCC 14 et suivants en font une erreur. En -std=c23, ou avec le mode par défaut de GCC 15 (gnu23), elle est disponible. Si tu dois compiler en C17 strict, ajoute #define _POSIX_C_SOURCE 200809L avant les #include.
Exemple
#include <stdio.h>#include <stdlib.h>#include <string.h>
int main(void){ char tampon[32] = "brouillon"; char *copie = strdup(tampon);
if (copie == NULL) return 1; strcpy(tampon, "écrasé"); printf("tampon = %s, copie = %s\n", tampon, copie); free(copie); return 0;}$ gcc -Wall -Wextra -g duplique.c -o duplique$ ./dupliquetampon = écrasé, copie = brouillon$ valgrind -q ./dupliquetampon = écrasé, copie = brouillon$ gcc -std=c17 -Wall -Wextra duplique.c -o duplique17duplique.c: In function 'main':duplique.c:8:19: error: implicit declaration of function 'strdup'; did you mean 'strcmp'? [-Wimplicit-function-declaration] 8 | char *copie = strdup(tampon); | ^~~~~~ | strcmpduplique.c:8:19: error: initialization of 'char *' from 'int' makes pointer from integer without a cast [-Wint-conversion]$ gcc -std=c23 -Wall -Wextra duplique.c -o duplique23$ ./duplique23tampon = écrasé, copie = brouillonÉcraser tampon ne change pas copie, qui vit dans son propre bloc sur le tas. Valgrind en mode -q ne dit rien : le bloc est bien libéré. En C17 strict, la fonction n'est pas déclarée et la compilation échoue ; en C23, elle passe sans rien changer au code.
strdup
Écris gm_strdup, qui réserve avec malloc la longueur de la chaîne plus un octet pour le terminateur, puis copie la chaîne dans ce bloc.