web-dev-qa-db-fra.com

Pourquoi strdup est-il considéré comme diabolique?

J'ai vu des affiches indiquant que strdup est diabolique. Y a-t-il un consensus à ce sujet? Je l'ai utilisé sans aucun sentiment de culpabilité et je ne vois aucune raison pour laquelle c'est pire que d'utiliser malloc/memcpy

La seule chose que je peux penser pourrait gagner une réputation strdup, c’est que les appelants pourraient en faire un mauvais usage (par exemple, ne pas se rendre compte qu’ils doivent libérer la mémoire retournée; essayer de strcat jusqu’à la fin d’une chaîne de caractères). Mais alors les cordes mallocées ne sont pas exemptes de la possibilité d’abus.


Merci pour les réponses et excuses à ceux qui considèrent que la question est inutile (vote à venir). En résumé, il semble qu'il n'y ait pas de sentiment général que strdup soit un mal en soi, mais un consensus général selon lequel il peut, comme beaucoup d'autres parties de C, être utilisé de manière incorrecte ou non sécurisée. 

Il n’existe pas vraiment de réponse «correcte», mais pour en accepter une, j’ai accepté la réponse de @nneoneo - elle aurait également pu être celle de @R ...

24
William Morris

Je peux penser à deux raisons:

  1. Ce n'est pas strictement ANSI C, mais plutôt POSIX. Par conséquent, certains compilateurs (par exemple, MSVC) découragent l'utilisation (MSVC préfère _strdup) et techniquement le standard C pourrait définir sa propre strdup avec une sémantique différente puisque str est un préfixe réservé. Son utilisation pose donc certains problèmes de portabilité.
  2. Il cache son allocation de mémoire. La plupart des autres fonctions str n'allouent pas de mémoire. Par conséquent, les utilisateurs peuvent être induits en erreur (comme vous le dites) en leur faisant croire que la chaîne renvoyée n'a pas besoin d'être libérée.

Mais, mis à part ces points, je pense qu’une utilisation prudente de strdup est justifiée, car elle peut réduire la duplication de code et fournit une implémentation de Nice pour les idiomes courants (telle que strdup("constant string") pour obtenir une copie modifiable et renvoyable d’une chaîne littérale).

31
nneonneo

Ma réponse est plutôt en faveur de strdup et ce n’est pas pire que toute autre fonction en C.

  1. POSIX est un standard et strdup n'est pas trop difficile à mettre en œuvre si la portabilité devient un problème. 

  2. La possibilité de libérer la mémoire allouée par strdup ne devrait pas être un problème si quelqu'un prenait un peu de temps pour lire la page de manuel et comprendre comment fonctionne strdup. Si on ne comprend pas le fonctionnement d'une fonction, il est très probable que la personne va gâcher quelque chose, cela s'applique à la fonction toute, pas seulement à strdup.

  3. En C, la mémoire et la plupart des choses sont gérées par le programmeur, donc strdup n'est pas pire que d'oublier la mémoire libremalloc 'ed, échouant à fin nulle une chaîne utilisant un format incorrect chaîne dans scanf (et invoquant un comportement indéfini), accédant à suspendu pointeur, etc.

(Je voulais vraiment poster ceci en tant que commentaire, mais je ne pouvais pas ajouter un seul commentaire. Par conséquent, posté en réponse).

19
P.P.

Je n'ai pas vraiment entendu strdup décrit comme étant diabolique, mais il y a des raisons pour lesquelles certaines personnes ne l'aiment pas:

  1. Ce n'est pas standard C (mais est dans POSIX). Cependant, je trouve cette raison ridicule, car il s’agit presque d’une fonction à une ligne qui permet d’ajouter des systèmes qui en sont dépourvus.
  2. La duplication aveugle de chaînes partout, plutôt que de les utiliser sur place chaque fois que cela est possible, fait perdre du temps et de la mémoire et introduit des cas d’échec dans du code qui pourrait sinon être exempt d’échec.
  3. Lorsque vous avez besoin d'une copie d'une chaîne, il est probable que vous aurez réellement besoin de plus d'espace pour la modifier ou la compléter, et strdup ne vous en donne pas la possibilité.
10
R..

Je pense que la majorité des préoccupations concernant strdup provient de préoccupations de sécurité concernant les dépassements de mémoire tampon et les chaînes mal formatées. Si une chaîne terminée non nulle est transmise à strdup, une chaîne de longueur non définie peut être allouée. Je ne sais pas si cela peut être spécifiquement utilisé dans une attaque, mais en général, il est recommandé de n'utiliser que des fonctions de chaîne qui prennent une longueur maximale au lieu de s'appuyer uniquement sur le caractère nul. 

5
john-charles

Évidemment, beaucoup de gens ne le font pas, mais personnellement, je trouve strdup mal pour plusieurs raisons,

  • le principal étant cela cache l'allocation. Les autres fonctions str* et la plupart des fonctions standard ne nécessitent pas free par la suite. strdup a donc l’air assez inoffensif et vous pouvez oublier de nettoyer après. dmckee a suggéré de simplement l'ajouter à votre liste mentale de fonctions qui doivent être nettoyées après, mais pourquoi? Je ne vois pas un grand avantage à réduire deux lignes de longueur moyenne à une seule.

  • Il alloue toujours de la mémoire sur le tas, et avec les VLA de C99 (est-ce 99?), Vous avez encore une autre raison d'utiliser simplement strcpy (vous n'avez même pas besoin de malloc). Vous ne pouvez pas toujours faire cela, mais quand vous le pouvez, vous devriez le faire.

  • Cela ne fait pas partie de la norme ISO (mais ça fait partie de la norme POSIX, merci Wiz), mais c'est vraiment un petit point, car R .. a mentionné que cela peut être ajouté facilement. Si vous écrivez des programmes portables, je ne sais pas comment vous diriez s'il est déjà défini ou non ...

Ce sont bien sûr quelques-unes de mes propres raisons, personne d'autre. Pour répondre à votre question, il n'y a pas de consensus à ma connaissance.

Si vous écrivez des programmes uniquement pour vous-même et que strdup ne pose aucun problème, il y a donc beaucoup moins de raisons de ne pas l'utiliser que si vous écrivez un programme destiné à être lu par de nombreuses personnes de différents niveaux et techniques.

2
Seth Carnegie

La raison pour laquelle je n'aime pas strdup, ce qui n'a pas été mentionné, est qu'il s'agit d'une allocation de ressources sans paire naturelle. Essayons un jeu idiot: je dis malloc, vous dites free. Je dis open vous dites close. Je dis create vous dites destroy. Je dis strdup vous dites ....? 

En fait, la réponse à strdup est free bien sûr, et la fonction aurait été mieux nommée malloc_and_strcpy pour que cela soit clair. Mais beaucoup de programmeurs C ne le voient pas de cette façon et oublient que strdup nécessite son opposé ou "fin" free pour désallouer. 

D'après mon expérience, il est très courant de trouver des fuites de mémoire dans le code appelé strdup. C'est une fonction étrange qui combine strlen, malloc et strcpy

1
Björn Lindqvist