6
votes

Strcpy lorsque le tampon Dest est plus petit que le tampon SRC

J'essaie de comprendre la différence / les inconvénients de Strcpy et Strncpy. Quelqu'un peut-il vous aider:

this is a long string 
a long string 


5 commentaires

Ceci s'appelle le dépassement de la mémoire tampon.


Ce problème de débordement tampon illustre pourquoi vous devriez choisir d'utiliser STRNCOPY sur Strcpy.


Je ne pouvais pas reproduire votre code. Je reçois Tring dans le tableau DEST.


@Spidey, c'est un comportement indéfini. C-FAQ.com/ansi/undef.html " Undefined: < / B> Que ce soit du tout peut arriver; la norme n'empose aucune exigence. Le programme peut ne pas compiler, ou il peut s'exécuter de manière incorrecte (en cas de collision ou de génération de résultats incorrects silencieusement), ou peut faire exactement exactement ce que le programmateur a voulu. "


Merci a tous. Surtout parce que vous avez non seulement expliqué la réponse, mais vous avez montré graphiquement comment cela fonctionne dans la mémoire (pour le comportement indiqué dans mon cas). A également noté que cela pourrait vomir différents résultats car ce comportement indéfini.


7 Réponses :


7
votes

Ceci est un débordement tampon et un comportement non défini.

Dans votre cas, il semble que le compilateur a placé Dest et src séquentiellement en mémoire. Lorsque vous copiez des src à Dest , il continue de copier au-delà de la fin de Dest et écrase une partie de src .


5 commentaires

Pouvez-vous s'il vous plaît être plus descriptif. Considérons simplement que mes devises et SRC sont séquentielles en mémoire. Donc, ils devraient commencer à partir de l'emplacement 1000 (par exemple) .. SO DESTS prend 1000-1004 (5 octets) et SRC prend 22 octets (21 caractères + résiliation null). Nous avons donc utilisé un total de 27 octets de 1000 à 1026. Si ce que j'ai mentionné (en termes de mémoire) est correct, pouvez-vous expliquer en détail comment le SRC s'est écrasé?


Et SRC et DST semblent être alignés sur des multiples de 4 caractères, de sorte que les cartouches 5 caractères, le nouveau SRC mangelé démarrera 8 caractères dans le SRC original (qui est maintenant DEST).


Pouvez-vous s'il vous plaît expliquer la carte mémoire afin qu'elle devienne plus facile à comprendre? Supposons simplement que toute la mémoire allouée commence à partir de l'emplacement 1000 .. Pouvez-vous expliquer les espaces occupés par DEST et SRC avant et après le Strcpy.


L'espace occupé par DEST et SRC ne change pas. La quantité d'espace allouée pour eux est constante. Quel changement est le contenu réel de la mémoire. Parce que vous causez une dépassement de tampon dans votre copie, vous ne modifiez pas simplement la zone de mémoire allouée à des devises, mais également une partie de la mémoire allouée pour SRC.


J'ai ajouté une explication graphique à ma réponse ci-dessous.



1
votes

Avec une bonne affaire, la chaîne est exacte voisines. Donc, dans votre cas, vous pouvez avoir cette image

DST | | | | | SRC | | | | | |

Donc, vous commencez à écrire et il arrive que les champs de SRC sont écrasés.

Hofferver Vous ne pouvez certainement pas compter sur elle. Tout pourrait arriver ce que vous avez est un comportement indéfini. Alors quelque chose d'autre peut arriver sur un autre ordinateur un autre temps et / ou d'autres options.

Cordialement Friedrich


0 commentaires

0
votes

Je suggère une lecture rapide de:

http://fr.wikipedia.org/wiki/strncpy#strncpy

qui vous montre les différences. Essentiellement Strncpy vous permet de spécifier un certain nombre d'octets à copier, ce qui signifie que la chaîne résultante n'est pas nécessairement nullterminée.

Maintenant, lorsque vous utilisez Strcpy pour copier une chaîne sur une autre, elle ne vérifie pas la zone de mémoire résultante pour voir si elle est assez grande - elle ne tient pas la main à cet égard. Il vérifie le caractère null dans la chaîne SRC.

Bien sûr, DST dans cet exemple n'est que de 5 octets. Alors, que se passe-t-il? Il continue à écrire, à la fin des devises et au-delà de la mémoire en mémoire. Et dans ce cas, la partie suivante de la mémoire sur la pile est votre chaîne SRC. Ainsi, alors que votre code ne le copie pas intentionnellement, la mise en page d'octets en mémoire couplée à l'écriture passé la fin de DST a causé cela.

espère que cela aide!


0 commentaires

11
votes

La réponse facile est que vous avez (avec cet appel Strcpy ()) fait quelque chose à l'extérieur des spécifications du système et souffrez donc de comportement non défini.

La réponse la plus difficile implique d'examiner la mise en page de mémoire concrète sur votre système, et comment Strcpy () fonctionne en interne. Cela va probablement quelque chose comme ceci: p> xxx pré>

Les lettres d code> support pour les octets dans DEST, les lettres p code> pétards octets, les caractères 0 code> sont des caractères ASCII NUL utilisées sous forme de terminateurs à chaîne. p>

MAINTUN StrcPy (Dest, SRC) changera quelque peu la mémoire (la présumer correctement les zones de mémoire qui se chevauche ): p>

     N+28 "g0PP"
     N+24 "trin"
     N+20 "g0 s"
     N+16 "trin"
     N+12 "ng s"
src  N+08 "a lo"
     N+04 " is "
dest N+00 "this"


0 commentaires

1
votes

Votre code a provoqué un débordement de mémoire tampon - la copie sur des caractères de destin qu'il peut tenir. Les caractères supplémentaires ont été écrits sur un autre endroit sur la pile, dans votre cas, où SRC pointait.

Vous devez utiliser strncpy () fonction.


0 commentaires

0
votes

soit je suis mal compris votre question, soit vous êtes mal compris que Strcpy:

question: je ne comprends pas, comment le SPING STIVE SCING A MODIFIÉ. Selon explication, Strcpy devrait garder copier jusqu'à ce qu'il rencontre un '\ 0', donc ça fait, mais comment se fait "Src 'String a eu modifié.

Il me semble que vous attendez que Strcpy arrête de copier dans DEST lorsqu'il atteigne la fin des devises, sur la base de voir un caractère \ 0 . Ce n'est pas ce que ça fait. Copie Strcpy dans la destination jusqu'à atteindre la fin de la chaîne source, délimitée par un caractère \ 0 . Il suppose que vous avez alloué suffisamment de mémoire pour la copie. Avant que la copie, le tampon Dest puisse avoir quelque chose, y compris tous les NULLS.

Strncpy résout cela en vous demandant de le dire à quel point la tampon est grande que vous copiez dans l'est, vous pouvez donc éviter les cas où il copie plus que ce qui peut s'adapter.


0 commentaires

1
votes

Comme une note supplémentaire, veuillez garder à l'esprit que la fonction Strncpy n'est pas la fonction appropriée à utiliser lorsque vous devez effectuer une copie avec une protection contre la mémoire tampon. Cette fonction n'est pas destinée à cette fin et n'a jamais été destinée à cette fin. Strncpy est une fonction créée il y a longtemps il y a longtemps pour effectuer une copie de chaîne très spécifique à l'application dans un système de fichiers très spécifique dans une ancienne version de UNIX. Malheureusement, les auteurs de la bibliothèque ont réussi à "HighJack" le nom générique-sondage Strncpy à utiliser pour cet objectif très étroit et spécifique. Il a ensuite été préservé à des fins de compatibilité en arrière. Et maintenant, nous avons une génération ou deux de programmeurs qui effectuent les hypothèses sur Strncpy basé uniquement sur son nom, et l'utilisent donc de manière incorrecte. En réalité, Strncpy a très peu ou pas d'utilisations significatives du tout.

C Bibliothèque standard (au moins sa version C89 / 90) n'offre aucune fonction de copie de chaîne avec une protection tampon de dépassement de tampon. Afin d'effectuer une copie protégée, vous devez utiliser une fonction spécifique à la plate-forme, comme Strlcpy , Strcpy_s ou écrire un vous-même.

PS Ce thread sur Stackoverflow contient Une bonne discussion sur le but réel strncpy a été développé pour. Voir cette Poster spécialement pour l'explication précise de son rôle dans Système de fichiers UNIX. Aussi, voir ici pour un bon article sur la façon dont strncpy est venu être.

Encore une fois, Strncpy est une fonction permettant de copier un type de chaîne complètement différent - une chaîne de longueur fixe. Il n'est même pas destiné à être utilisé avec des chaînes traditionnelles terminées de style C.


7 commentaires

Je trouve Strncpy utile dire si j'ai un tampon et que je lis des lignes de lecture d'un fichier texte que je connais sera


@James Morris: Je ne vois pas ce que vous essayez exactement de réaliser en utilisant strncpy là-bas. Quelle caractéristique de strncpy est importante pour vous dans ce cas?


Cette réponse de cette façon n'est pas correcte. Strncpy ne sera sûrement pas dépassé un tampon si vous) avez le bon espace pour la "chaîne" b) que vous obtenez bien avec la longueur. Pour cela, tout ce que vous utilisez probablement mieux le code suivant (pseudo-c, partiellement pris de Code complet II) Char BUF [MAX_LEN + 1]; Strncpy (buf, src, max_len); Dans ce cas, Strncpy est plus sûr, alors Strcpy. Mais vous avez raison, il n'ya pas une fonction dans la norme C que «tampon» dépassait la protection. C'est simplement comment C a été mis en œuvre, la vitesse, la vitesse, la vitesse


@Friedrich: La réponse est correcte. Strncpy Est-ce que beaucoup d'inutile fonctionnent lorsque la chaîne est plus courte que la mémoire tampon (remplit la partie arrière avec des zéros) et ne fait pas ce qui doit être fait lorsque la chaîne est plus longue que la mémoire tampon ( n'ajoute pas le zéro terminateur). Ce sont des conséquences d'un simple fait que strncpy a été initialement développé pour un but complètement différent. Vrai, il est possible de sauter à travers certains cerveaux pour faire Strncpy "Travail" ici aussi, mais ce n'est toujours pas le bon outil pour le travail. (Vous dans votre "pseudocode", j'ai oublié d'initialiser le zéro terminatie également.)


J'ai ajouté un P.S. Pour ma réponse contenant des liens utiles pouvant aider à comprendre le but réel de la fonction Strncpy .


@Andreyt: citant la page de l'homme, "sauf que, au plus N octets de SRC de SRC sont copiés" serait la caractéristique de Strncpy qui est important. Je n'ai pas réalisé que Strncpy a fait tout ce rembourrage. Bravo pour P.S.


Les «chaînes» à zéro ne sont pas aussi communes qu'auparavant, mais ils sont à peine "spécifique à l'application". La fonction Strncpy est la bonne chose à utiliser si par ex. A Char [8] est utilisé pour contenir jusqu'à huit caractères (plutôt que sept) et code qui utilise le contenu de celui-ci connaîtra la longueur maximale. Notez que memcpy ou strncpy pourrait être utilisé si la source et la destination sont des tampons rembourrés de la même longueur, mais memcpy serait probablement plus rapide. Le temps d'utiliser strncpy est lorsque la source est zéro- terminée et la destination est zéro- rembourré .