J'ai lu sur Stack Overflow que certaines fonctions C sont "obsolètes" ou "devraient être évitées". Pouvez-vous me donner quelques exemples de ce type de fonction et pourquoi?
Quelles alternatives à ces fonctions existent?
Pouvons-nous les utiliser en toute sécurité - des bonnes pratiques?
c
standard-library
obsolete
Andrei Ciobanu
la source
la source
strncpy()
comme remplacement général pourstrcpy()
, et je n'utiliseraisstrncat()
jamais parce qu'il a l'interface la plus peu intuitive imaginable - savez-vous ce que le paramètre de longueur spécifie?Réponses:
Fonctions
obsolètes non sécurisées
Un exemple parfait d'une telle fonction est gets () , car il n'y a aucun moyen de lui indiquer la taille du tampon de destination. Par conséquent, tout programme qui lit l'entrée à l'aide de gets () a une vulnérabilité de dépassement de mémoire tampon . Pour des raisons similaires, il faut utiliser strncpy () à la place de strcpy () et strncat () à la place de strcat () .
Pourtant, d'autres exemples incluent les fonctions tmpfile () et mktemp () en raison de problèmes de sécurité potentiels liés à l'écrasement des fichiers temporaires et qui sont remplacées par la fonction plus sécurisée mkstemp () .
Non-réentrant
D'autres exemples incluent gethostbyaddr () et gethostbyname () qui ne sont pas réentrants (et, par conséquent, ne sont pas garantis d'être threadsafe) et ont été remplacés par les réentrants getaddrinfo () et freeaddrinfo () .
Vous remarquerez peut-être un modèle ici ... soit le manque de sécurité (éventuellement en omettant d'inclure suffisamment d'informations dans la signature pour éventuellement l'implémenter en toute sécurité) ou la non-réentrance sont des sources courantes de dépréciation.
Désuet, non portable
Certaines autres fonctions deviennent simplement obsolètes car elles dupliquent des fonctionnalités et ne sont pas aussi portables que d'autres variantes. Par exemple, bzero () est obsolète au profit de memset () .
Sécurité des fils et réentrance
Vous avez posé une question, dans votre message, sur la sécurité des fils et la réentrance. Il y a une légère différence. Une fonction est réentrante si elle n'utilise aucun état partagé et mutable. Ainsi, par exemple, si toutes les informations dont elle a besoin sont transmises à la fonction et que tous les tampons nécessaires sont également passés à la fonction (plutôt que partagés par tous les appels à la fonction), alors il est réentrant. Cela signifie que différents threads, en utilisant des paramètres indépendants, ne risquent pas de partager accidentellement l'état. La réentrance est une garantie plus solide que la sécurité des fils. Une fonction est thread-safe si elle peut être utilisée par plusieurs threads simultanément. Une fonction est thread-safe si:
En général, dans la spécification UNIX unique et IEEE 1003.1 (c'est-à-dire "POSIX"), toute fonction qui n'est pas garantie d'être réentrante n'est pas garantie d'être thread-safe. Ainsi, en d'autres termes, seules les fonctions qui sont garanties réentrantes peuvent être utilisées de manière portative dans des applications multithread (sans verrouillage externe). Cela ne signifie pas, cependant, que les implémentations de ces normes ne peuvent pas choisir de rendre une fonction non réentrante threadsafe. Par exemple, Linux ajoute fréquemment la synchronisation aux fonctions non réentrantes afin d'ajouter une garantie (au-delà de celle de la spécification UNIX unique) de la sécurité des threads.
Chaînes (et tampons mémoire, en général)
Vous avez également demandé s'il y avait un défaut fondamental avec les chaînes / tableaux. Certains pourraient prétendre que c'est le cas, mais je dirais que non, il n'y a pas de défaut fondamental dans la langue. C et C ++ vous obligent à transmettre la longueur / capacité d'un tableau séparément (ce n'est pas une propriété ".length" comme dans certains autres langages). Ce n'est pas un défaut en soi. Tout développeur C et C ++ peut écrire du code correct simplement en passant la longueur en tant que paramètre si nécessaire. Le problème est que plusieurs API qui nécessitaient ces informations n'ont pas réussi à les spécifier en tant que paramètre. Ou supposé qu'une certaine constante MAX_BUFFER_SIZE serait utilisée. Ces API sont désormais obsolètes et remplacées par des API alternatives qui permettent de spécifier les tailles de tableau / tampon / chaîne.
Scanf (En réponse à votre dernière question)
Personnellement, j'utilise la librairie C ++ iostreams (std :: cin, std :: cout, les opérateurs << et >>, std :: getline, std :: istringstream, std :: ostringstream , etc.), donc je ne m'occupe généralement pas de cela. Si j'étais obligé d'utiliser du C pur, personnellement, j'utiliserais simplement fgetc () ou getchar () en combinaison avec strtol () , strtoul () , etc. et analyserais les choses manuellement, car je ne suis pas un grand fan de varargs ou chaînes de format. Cela dit, à ma connaissance, il n'y a pas de problème avec [f] scanf () , [f] printf (), etc. tant que vous créez vous-même les chaînes de format, vous ne transmettez jamais de chaînes de format arbitraires ou n'autorisez pas l'utilisation des entrées utilisateur comme chaînes de format, et vous utilisez les macros de formatage définies dans <inttypes.h> le cas échéant. (Remarque, snprintf () doit être utilisé à la place de sprintf () , mais cela a à voir avec l'échec de spécifier la taille du tampon de destination et non l'utilisation de chaînes de format). Je dois également souligner que, en C ++, boost :: format fournit un formatage de type printf sans varargs.
la source
strncpy
devrait généralement être évité. Il ne fait pas ce que la plupart des programmeurs supposent. Il ne garantit pas la terminaison (conduisant à des dépassements de mémoire tampon), et il remplit des chaînes plus courtes (pouvant dégrader les performances dans certains cas).strncpy()
ni le pirestrncat()
n'est un remplacement judicieux pour les variantes n-less.Une fois de plus, les gens répètent, comme un mantra, l'affirmation ridicule selon laquelle la version "n" des fonctions str sont des versions sûres.
Si c'était ce à quoi ils étaient destinés, ils finiraient toujours par null.
Les versions «n» des fonctions ont été écrites pour être utilisées avec des champs de longueur fixe (comme les entrées de répertoire dans les premiers systèmes de fichiers) où le terminateur nul n'est requis que si la chaîne ne remplit pas le champ. C'est aussi la raison pour laquelle les fonctions ont des effets secondaires étranges qui sont inefficaces si elles sont simplement utilisées comme remplacements - prenez strncpy () par exemple:
Les tampons alloués pour gérer les noms de fichiers étant généralement de 4 Ko, cela peut entraîner une détérioration massive des performances.
Si vous voulez des versions "soi-disant" sûres, procurez-vous - ou écrivez vos propres - routines strl (strlcpy, strlcat etc.) qui terminent toujours les chaînes et n'ont pas d'effets secondaires. Veuillez noter cependant que ceux-ci ne sont pas vraiment sûrs car ils peuvent tronquer la chaîne en silence - c'est rarement le meilleur plan d'action dans un programme réel. Il y a des occasions où cela est acceptable, mais il y a aussi de nombreuses circonstances où cela pourrait conduire à des résultats catastrophiques (par exemple, l'impression d'ordonnances médicales).
la source
strncpy()
, mais vous avez tortstrncat()
.strncat()
n'a pas été conçu pour être utilisé avec des champs de longueur fixe - il a en fait été conçu pour être unstrcat()
qui limite le nombre de caractères concaténés. Il est assez facile de l'utiliser comme un "coffre-fortstrcat()
" en gardant une trace de l'espace restant dans le tampon lors de plusieurs concaténations, et encore plus facile de l'utiliser comme un "coffre-fortstrcpy()
" (en définissant le premier caractère du tampon de destination sur'\0'
avant l'appelant). terminestrncat()
toujours la chaîne de destination et n'écrit pas de'\0'
s supplémentaires .strncat()
la destination n'est pas toujours nulle et qu'elle a été conçue pour être utilisée avec des champs de longueur fixe, qui sont tous deux erronés.strncat()
fonctionnera correctement quelle que soit la longueur de la chaîne source, maisstrcat()
pas. Le problème avecstrlcat()
ici est que ce n'est pas une fonction C standard.Plusieurs réponses suggèrent ici d'utiliser
strncat()
overstrcat()
; Je suggère questrncat()
(etstrncpy()
) devrait également être évité. Il a des problèmes qui le rendent difficile à utiliser correctement et conduisent à des bugs:strncat()
est lié (mais pas tout à fait exactement - voir le 3ème point) au nombre maximum de caractères qui peuvent être copiés vers la destination plutôt qu'à la taille du tampon de destination. Cela rendstrncat()
plus difficile à utiliser qu'il ne devrait l'être, en particulier si plusieurs éléments seront concaténés à la destination.s1
eststrlen(s1)+n+1
" pour un appel qui ressemble àstrncat( s1, s2, n)
strncpy()
a également un problème qui peut entraîner des bogues que vous essayez de l'utiliser de manière intuitive - cela ne garantit pas que la destination est terminée par null. Pour vous assurer que vous devez vous assurer de gérer spécifiquement ce cas d'angle en déposant vous-même un'\0'
dans le dernier emplacement du tampon (au moins dans certaines situations).Je suggère d'utiliser quelque chose comme OpenBSD
strlcat()
etstrlcpy()
(bien que je sache que certaines personnes n'aiment pas ces fonctions; je pense qu'elles sont beaucoup plus faciles à utiliser en toute sécurité questrncat()
/strncpy()
).Voici un peu de ce que Todd Miller et Theo de Raadt avaient à dire sur les problèmes avec
strncat()
etstrncpy()
:L'audit de sécurité d'OpenBSD a révélé que les bogues avec ces fonctions étaient «endémiques». Contrairement
gets()
, ces fonctions peuvent être utilisées en toute sécurité, mais dans la pratique, il y a beaucoup de problèmes car l'interface est déroutante, peu intuitive et difficile à utiliser correctement. Je sais que Microsoft a également fait des analyses (bien que je ne sache pas combien de leurs données ils ont pu publier), et en conséquence a interdit (ou du moins très fortement découragé - l'interdiction pourrait ne pas être absolue) le utilisation destrncat()
etstrncpy()
(entre autres fonctions).Quelques liens avec plus d'informations:
la source
memmove()
. (Eh bien, vous pouvez utilisermemcpy()
dans le cas normal lorsque les chaînes sont indépendantes.)strncat()
toujours la chaîne de destination.strncat()
. Cependant, il est correct pourstrncpy()
, ce qui présente d'autres problèmes.strncat()
est un remplacement raisonnable pourstrcat()
, maisstrncpy()
n'est pas un remplacement raisonnable pourstrcpy()
.strncat()
n'est pas toujours nulle. Je confondais un peu les comportements destrncat()
etstrncpy()
(une autre raison pour laquelle ils sont des fonctions à éviter - ils ont des noms qui impliquent des comportements similaires, mais en fait se comportent différemment de manière importante ...). J'ai modifié ma réponse pour corriger cela et ajouter des informations supplémentaires.char str[N] = ""; strncat(str, "long string", sizeof(str));
s'agit d'un débordement de tampon si N n'est pas assez grand. Lastrncat()
fonction est trop facile à utiliser à mauvais escient; il ne doit pas être utilisé. Si vous pouvez utiliser enstrncat()
toute sécurité, vous auriez pu utilisermemmove()
ou à lamemcpy()
place (et ceux-ci seraient plus efficaces).Fonctions de bibliothèque standard qui ne doivent jamais être utilisées:
setjmp.h
setjmp()
. Ensemblelongjmp()
, ces fonctions sont largement reconnues comme étant incroyablement dangereuses à utiliser: elles mènent à la programmation spaghetti, elles sont accompagnées de nombreuses formes de comportement indéfini, elles peuvent provoquer des effets secondaires involontaires dans l'environnement du programme, comme affecter les valeurs stockées sur la pile. Références: MISRA-C: 2012 rule 21.4, CERT C MSC22-C .longjmp()
. Voirsetjmp()
.stdio.h
gets()
. La fonction a été supprimée du langage C (selon C11), car elle n'était pas sûre selon la conception. La fonction était déjà signalée comme obsolète dans C99. Utilisezfgets()
plutôt. Références: ISO 9899: 2011 K.3.5.4.1, voir également la note 404.stdlib.h
atoi()
famille de fonctions. Ceux-ci n'ont pas de gestion des erreurs mais invoquent un comportement non défini chaque fois que des erreurs se produisent. Fonctions complètement superflues qui peuvent être remplacées par lastrtol()
famille de fonctions. Références: MISRA-C: 2012 rule 21.7.string.h
strncat()
. A une interface maladroite qui est souvent mal utilisée. C'est surtout une fonction superflue. Voir également les remarques pourstrncpy()
.strncpy()
. L'intention de cette fonction n'a jamais été d'être une version plus sûre destrcpy()
. Son seul but a toujours été de gérer un ancien format de chaîne sur les systèmes Unix, et le fait qu'il soit inclus dans la bibliothèque standard est une erreur connue. Cette fonction est dangereuse car elle peut laisser la chaîne sans terminaison nulle et les programmeurs sont connus pour l'utiliser souvent de manière incorrecte. Références: Pourquoi strlcpy et strlcat sont-ils considérés comme non sécurisés? .Fonctions de bibliothèque standard à utiliser avec précaution:
assert.h
assert()
. Livré avec une surcharge et ne doit généralement pas être utilisé dans le code de production. Il est préférable d'utiliser un gestionnaire d'erreurs spécifique à l'application qui affiche les erreurs mais ne ferme pas nécessairement l'ensemble du programme.signal.h
signal()
. Références: MISRA-C: 2012 rule 21.5, CERT C SIG32-C .stdarg.h
va_arg()
famille de fonctions. La présence de fonctions de longueur variable dans un programme C est presque toujours une indication d'une mauvaise conception du programme. Doit être évité sauf si vous avez des exigences très spécifiques.stdio.h
En général, toute cette bibliothèque n'est pas recommandée pour le code de production , car elle est accompagnée de nombreux cas de comportement mal défini et de sécurité de type médiocre.
fflush()
. Parfaitement bien à utiliser pour les flux de sortie. Appelle un comportement non défini s'il est utilisé pour les flux d'entrée.gets_s()
. Version sûre degets()
incluse dans l'interface de vérification des limites C11. Il est préférable d'utiliser à lafgets()
place, conformément à la recommandation standard C. Références: ISO 9899: 2011 K.3.5.4.1.printf()
famille de fonctions. Fonctions lourdes en ressources qui s'accompagnent de nombreux comportements indéfinis et d'une mauvaise sécurité de type.sprintf()
a également des vulnérabilités. Ces fonctions doivent être évitées dans le code de production. Références: MISRA-C: 2012 rule 21.6.scanf()
famille de fonctions. Voir les remarques surprintf()
. De plus, -scanf()
est vulnérable aux dépassements de tampon s'il n'est pas utilisé correctement.fgets()
est préférable d'utiliser lorsque cela est possible. Références: CERT C INT05-C , MISRA-C: 2012 rule 21.6.tmpfile()
famille de fonctions. Livré avec divers problèmes de vulnérabilité. Références: CERT C FIO21-C .stdlib.h
malloc()
famille de fonctions. Parfaitement utilisable dans les systèmes hébergés, mais soyez conscient des problèmes bien connus de C90 et ne diffusez donc pas le résultat . Lamalloc()
famille de fonctions ne doit jamais être utilisée dans des applications autonomes. Références: MISRA-C: 2012 rule 21.3.Notez également que cela
realloc()
est dangereux si vous écrasez l'ancien pointeur avec le résultat derealloc()
. En cas d'échec de la fonction, vous créez une fuite.system()
. Livré avec beaucoup de frais généraux et bien que portable, il est souvent préférable d'utiliser des fonctions API spécifiques au système à la place. Livré avec divers comportements mal définis. Références: CERT C ENV33-C .string.h
strcat()
. Voir les remarques pourstrcpy()
.strcpy()
. Parfaitement bien à utiliser, sauf si la taille des données à copier est inconnue ou supérieure à la mémoire tampon de destination. Si aucune vérification de la taille des données entrantes n'est effectuée, il peut y avoir des dépassements de tampon. Ce qui n'est pas une faute enstrcpy()
soi, mais de l'application appelante - quistrcpy()
n'est pas sûre est principalement un mythe créé par Microsoft .strtok()
. Modifie la chaîne de l'appelant et utilise des variables d'état internes, ce qui pourrait la rendre dangereuse dans un environnement multi-thread.la source
static_assert()
à la place deassert()
, si la condition peut être résolue au moment de la compilation. En outre,sprintf()
peut presque toujours être remplacé,snprintf()
ce qui est un peu plus sûr.strtok()
dans une fonction A signifie que (a) la fonction ne peut pas appeler une autre fonction qui utilise égalementstrtok()
pendant que A l'utilise, et (b) signifie qu'aucune fonction qui appelle A ne peut être utiliséestrtok()
lorsqu'elle appelle A. En d'autres termes, utiliserstrtok()
empoisonne la chaîne d'appel; il ne peut pas être utilisé en toute sécurité dans le code de la bibliothèque car il doit documenter qu'il utilisestrtok()
pour empêcher les autres utilisateurs d'strtok()
appeler le code de la bibliothèque.strncpy
est la fonction appropriée à utiliser lors de l'écriture d'un tampon de chaîne à zéro remplissage avec des données provenant soit d'une chaîne terminée par zéro, soit d'un tampon de remplissage à zéro dont la taille est au moins aussi grande que la destination. Les tampons sans rembourrage ne sont pas très courants, mais ils ne sont pas non plus vraiment obscurs.Certains prétendraient cela
strcpy
etstrcat
devraient être évités, en faveur destrncpy
etstrncat
. C'est quelque peu subjectif, à mon avis.Ils doivent absolument être évités lors du traitement des entrées utilisateur - sans aucun doute ici.
Dans le code "loin" de l'utilisateur, quand on sait juste que les tampons sont assez longs,
strcpy
etstrcat
peuvent être un peu plus efficaces car le calcul dun
passage à leurs cousins peut être superflu.la source
strlcat
etstrlcpy
, puisque la version 'n' ne garantit pas la terminaison NULL de la chaîne de destination.strncpy()
écrira exactement desn
octets, en utilisant des caractères nuls si nécessaire. Comme Dan, utiliser une version sûre est le meilleur choix de l'OMI.strncat()
peut être difficile à utiliser correctement et en toute sécurité (et doit être évité) est sur le sujet.Éviter
strtok
pour les programmes multithread car ce n'est pas thread-safe.gets
car cela pourrait provoquer un débordement de tamponla source
strtok()
va un peu au-delà de la sécurité des threads - ce n'est pas sûr même dans un programme à thread unique, à moins que vous ne sachiez avec certitude qu'aucune fonction que votre code pourrait appeler lors de l'utilisationstrtok()
ne l' utilise pas également (ou ils gâcherontstrtok()
l'état de sous vous). En fait, la plupart des compilateurs qui ciblent les plates-formes multi-thread prennent en chargestrtok()
les problèmes potentiels de threads en utilisant le stockage local des threads pourstrtok()
les données statiques de. Mais cela ne résout toujours pas le problème des autres fonctions qui l'utilisent pendant que vous êtes (dans le même thread).strtok()
est qu'il ne conserve précisément qu'un seul tampon pour travailler, donc la plupart des bons remplacements nécessitent de conserver une valeur de tampon et de la transmettre.strcspn
fait l'essentiel de ce dont vous avez besoin - trouvez le prochain séparateur de jetons. Vous pouvez réimplémenter une variante sensée destrtok
avec.Il vaut probablement la peine d'ajouter à nouveau que ce
strncpy()
n'est pas le remplacement à usage général de cestrcpy()
que son nom pourrait suggérer. Il est conçu pour les champs de longueur fixe qui n'ont pas besoin d'un nul-terminator (il a été initialement conçu pour être utilisé avec les entrées de répertoire UNIX, mais peut être utile pour des choses comme les champs de clé de chiffrement).Il est cependant facile de l'utiliser
strncat()
en remplacement destrcpy()
:(Le
if
test peut évidemment être abandonné dans le cas courant, où vous savez quedest_size
c'est certainement différent de zéro).la source
Consultez également la liste des API interdites de Microsoft . Ce sont des API (dont beaucoup sont déjà répertoriées ici) qui sont interdites du code Microsoft car elles sont souvent mal utilisées et entraînent des problèmes de sécurité.
Vous n'êtes peut-être pas d'accord avec tous, mais ils valent tous la peine d'être pris en considération. Ils ajoutent une API à la liste lorsque son utilisation abusive a conduit à un certain nombre de bogues de sécurité.
la source
Presque toutes les fonctions qui traitent des chaînes terminées par NUL sont potentiellement dangereuses. Si vous recevez des données du monde extérieur et que vous les manipulez via les fonctions str * (), vous vous préparez à une catastrophe
la source
N'oubliez pas sprintf - c'est la cause de nombreux problèmes. Cela est vrai car l'alternative, snprintf a parfois des implémentations différentes qui peuvent rendre votre code non portable.
linux: http://linux.die.net/man/3/snprintf
fenêtres: http://msdn.microsoft.com/en-us/library/2ts7cx93%28VS.71%29.aspx
Dans le cas 1 (linux), la valeur de retour est la quantité de données nécessaire pour stocker la totalité du tampon (si elle est plus petite que la taille du tampon donné, la sortie a été tronquée)
Dans le cas 2 (fenêtres), la valeur de retour est un nombre négatif au cas où la sortie serait tronquée.
En général, vous devez éviter les fonctions qui ne sont pas:
buffer overflow safe (beaucoup de fonctions sont déjà mentionnées ici)
thread safe / non réentrant (strtok par exemple)
Dans le manuel de chaque fonction, vous devez rechercher des mots-clés tels que: safe, sync, async, thread, buffer, bugs
la source
_sprintf()
a été créé par Microsoft avant l'snprintf()
arrivée de la norme , IIRC. ´StringCbPrintf () ´ est assez similaire àsnprintf()
bien.sprintf
quelque sorte en toute sécurité , dans certains cas:sprintf(buffer,"%10s",input);
limite le nb copié octets à 10 (sibuffer
estchar buffer[11]
c'est sûr , même si les données peuvent liquider tronquée.Il est très difficile de l'utiliser en
scanf
toute sécurité. Une bonne utilisation descanf
peut éviter les débordements de tampon, mais vous êtes toujours vulnérable à un comportement indéfini lors de la lecture de nombres qui ne correspondent pas au type demandé. Dans la plupart des cas,fgets
suivie par l' auto-analyse syntaxique ( à l' aidesscanf
,strchr
etc.) est une meilleure option.Mais je ne dirais pas "éviter
scanf
tout le temps".scanf
a ses utilisations. À titre d'exemple, disons que vous souhaitez lire l'entrée utilisateur dans unchar
tableau de 10 octets de long. Vous souhaitez supprimer la nouvelle ligne de fin, le cas échéant. Si l'utilisateur entre plus de 9 caractères avant une nouvelle ligne, vous souhaitez stocker les 9 premiers caractères dans la mémoire tampon et tout ignorer jusqu'à la prochaine nouvelle ligne. Tu peux faire:Une fois que vous vous êtes habitué à cet idiome, il est plus court et à certains égards plus propre que:
la source
Dans tous les scénarios de copie / déplacement de chaîne - strcat (), strncat (), strcpy (), strncpy (), etc. - les choses se passent beaucoup mieux ( plus sûres ) si quelques heuristiques simples sont appliquées:
1. Toujours NUL-fill votre (vos) tampon (s) avant d'ajouter des données.
2. Déclarez les tampons de caractères comme [SIZE + 1], avec une macro-constante.
Par exemple, étant donné:
nous pouvons utiliser du code comme:
relativement sûr. Le memset () devrait apparaître avant strncpy (), même si nous avons initialisé Buffer au moment de la compilation, car nous ne savons pas ce que les autres codes placés dedans avant l'appel de notre fonction. Le strncpy () tronquera les données copiées en "1234567890" et ne les terminera pas par NUL. Cependant, comme nous avons déjà rempli tout le tampon NUL - sizeof (Buffer), plutôt que BUFSIZE - il est garanti qu'il y aura une terminaison finale NUL "hors de portée" de toute façon, tant que nous contraignons nos écritures à l'aide de BUFSIZE constante, au lieu de sizeof (Buffer).
Buffer et BUFSIZE fonctionnent également très bien pour snprintf ():
Même si snprintf () n'écrit spécifiquement que les caractères BUFIZE-1, suivis de NUL, cela fonctionne en toute sécurité. Donc, nous "gaspillons" un octet NUL superflu à la fin de Buffer ... nous évitons à la fois les conditions de dépassement de mémoire tampon et de chaînes non terminées, pour un coût mémoire assez faible.
Mon appel sur strcat () et strncat () est plus dur: ne les utilisez pas. Il est difficile d'utiliser strcat () en toute sécurité, et l'API pour strncat () est si contre-intuitive que l'effort nécessaire pour l'utiliser correctement annule tout avantage. Je propose le drop-in suivant:
Il est tentant de créer un drop-in strcat (), mais ce n'est pas une bonne idée:
car la cible peut être un pointeur (donc sizeof () ne renvoie pas les informations dont nous avons besoin). Je n'ai pas de bonne solution "universelle" aux instances de strcat () dans votre code.
Un problème que je rencontre fréquemment de la part des programmeurs «sensibles à strFunc ()» est une tentative de protection contre les débordements de tampon en utilisant strlen (). C'est très bien si le contenu est garanti pour être terminé par NUL. Sinon, strlen () lui-même peut provoquer une erreur de dépassement de tampon (conduisant généralement à une violation de segmentation ou à une autre situation de vidage de mémoire), avant que vous n'atteigniez le code "problématique" que vous essayez de protéger.
la source
atoi n'est pas thread-safe. J'utilise strtol à la place, conformément aux recommandations de la page de manuel.
la source
strtol()
serait thread-safe etatoi()
ne le serait pas.man atoi
(il devrait y en avoir, cependant).