7
votes

taille de ("...") dans Visual C ++ me rend malheureux

J'écris un morceau de code où j'utilise Tailleof ("suls") comme paramètre d'une fonction, j'ai remarqué que la fonction ne renvoyait pas la valeur attendue, donc je suis allé voir Le code ASM correspondant et j'ai trouvé une surprise désagréable. Est-ce que quelqu'un a une explication pour cela (voir la photo)?

Watch Fenêtre affiche Tailleof == 4, ASM 5

Je sais qu'il y a plus de 1000 façons différentes de faire cela, j'ai déjà mis en œuvre un autre d'entre eux, mais je veux connaître la raison derrière ce comportement.

Pour le curieux, c'est Visual Studio 2008 SP1.


8 commentaires

Dans le code ASM illustré à la ligne 2, il appuie le décalage de la chaîne "PDFA" N'EST-si celui du premier MEMCMP ? Avez-vous copié Coller le code ASM droit? Je suis sûr que le même problème se produit, mais votre image est fausse


VC10 fait souvent des erreurs lors de l'évaluation Tailleof Expressions de pointeurs et / ou de références dans la vue Watch. Cela ne s'est pas produit dans les versions précédentes. Utilisez-vous VC10?


Mis à part: Tailleof n'est pas une "fonction". Par conséquent, cela ne "retourne" rien. taille de est un opérateur. Une expression de taille d'analyse est évaluée à une valeur particulière.


Tailleof ("Données") est de 5 octets comptant la finale 0 de la matrice. Je soupçonne que l'inspecteur implémente-le en tant qu'appel de la fonction et convertit Char littéral au pointeur vers de la réponse à la réponse 4.


Débogueur! = Compilateur. Vous obtenez la taille d'un pointeur dans le débogueur. Il n'y a généralement aucun moyen pour le débogueur de connaître la taille d'un tableau.


@Hanspassant: D'autre part, la fenêtre immédiate, donnée une expression complète comme Tailleof ("abcde") , devrait donner un résultat correct ...


Pour vérifier si le débogueur interprète la chaîne en tant que pointeur, ajoutez simplement un nombre arbitraire de caractères à la chaîne de sorte que la longueur de la chaîne ne soit pas ambiguë avec la taille d'un pointeur (par exemple, rendre la chaîne "PDFA123123" < / code>)


@yms j'ai mentionné ci-dessus que le problème était probablement le même. Quoi qu'il en soit, lorsque vous faites des messages, vous devriez être aussi clair que possible.


7 Réponses :


6
votes

Il existe un terminateur C-String '\ 0' à la fin de chaque chaîne C afin "PDFA" est en fait le tableau de caractères suivants {'P', 'D', '" ',' \ 0 '} mais le \ 0 ne sera pas imprimé. Utilisez strylen ("PDFA") à la place.


0 commentaires

11
votes

La valeur 5 est correcte. La constante inclut l'octet de terminaison zéro. L'affichage de 4 dans la fenêtre de montre est celui qui ne semble pas être correct.


0 commentaires

7
votes

Les littéraux de chaîne sont de type "tableau de n const caractère " ([lex.string], ¶8), où n est le numéro de char S de laquelle la chaîne est composée. Étant donné que la chaîne est terminée null, taille de retournera le nombre de caractères "normaux" plus 1; La fenêtre de la montre est fausse, c'est probablement un bogue (comme @gene Bushuyev a dit, il l'interprément probablement comme un pointeur au lieu d'une matrice littérale =).

Le fait que la valeur 5 est intégrée au code est normale, étant taille de un opérateur de compilation.


2 commentaires

Et qu'en est-il du 4 dans la fenêtre de la montre?


@MOOINGDUCK: Probablement un bug; Je soutiens l'idée de Gene selon laquelle il est interprété comme un pointeur (au lieu d'un tableau), donnant ainsi le résultat de 4 octets (32 bits).



6
votes

N'oubliez pas que les chaînes C contiennent une extrémité zéro \ 0 . Cinq est la valeur correcte.


0 commentaires

4
votes

Eh bien, 5 est la valeur correcte de la taille de taille ("PDFA"). 4 caractères + zéro traînant.

Aussi, gardez à l'esprit que "le résultat ne correspond pas nécessairement à la taille calculée en ajoutant les exigences de stockage des membres individuels. L'option de compilateur / zp et le pack pragma affectent les limites d'alignement des membres."

Parler de la fenêtre de surveillance, je pense que cela vous montre simplement la taille du pointeur (Cons-Char *) lui-même. Essayez de recompiler le programme en mode 64 bits et vérifiez quelle fenêtre de montre montrerait alors. Si j'ai raison, alors vous verrez 8.


4 commentaires

L'emballage ne s'applique pas à cela, puisqu'un littéral à chaîne n'est pas une structure.


Je préfère garder la citation de MSDN intact.


Pour voir si la fenêtre de montre indique la taille du pointeur, vérifiez simplement si Tailleof ("PDFA") et Taillef ("pdfaalsdalsdas") ont la même valeur.


Ouais. Que 5 VS 4 caractères semblent toucher l'état des limites où la longueur de la chaîne est tellement similaire à la taille du pointeur :)



4
votes

La raison pour laquelle les choses vont mal ™ ici est que vous avez choisi un niveau d'abstraction trop bas, le memcmp .

Un niveau supérieur Vous avez STRCMP et WCSCMP .

et un niveau à partir de celui que vous avez std :: string et std :: wstring . .

La "vitesse" (HAH!) de l'abstraction possible de votre niveau le plus bas de votre choix est décalé par

  • résultat incorrect.

  • Inefficacité due au manque de connaissances de type (chaîne large ou étroite, votre code ne sait pas).

  • Inefficacité due au manque de connaissances de données (majuscules ou minuscules).

    Au lieu de perdre du temps sur la fixation des problèmes du code de niveau le plus bas inefficace et de perdre du temps sur la détermination des détails de dérivation des outils de faible niveau, utilisez un niveau d'abstraction plus élevé et plus sûr.


    Juste pour l'enregistrement, Tailleof ("ABCD") est 5. La fenêtre de la montre est probablement, comme l'a fait remarquer HANS Passant, affichant la taille d'un pointeur. Cependant, je ne suis pas d'accord avec HANS que le débogueur n'a généralement aucun moyen de connaître la taille d'un tableau: Pour une construction de débogage, elle peut savoir n'importe quoi et tout sur la source d'origine, y compris la source originale de Verbatim si nécessaire (et il affiche que Verbatim source originale, en contexte). Donc, que 4 est imho un bug d'une manière ou d'une autre. Soit un bogue dans le code de débogueur, soit un bogue dans sa conception.

    acclamations et hth.,


0 commentaires

2
votes

Sizeof est un opérateur qui évalue à une taille_t, généralement un Int non signé sur des plates-formes 32 bits. C'est pourquoi vous le voyez comme 4 dans le débogueur. La taille de l'opérateur est également une r devalue, vous ne pouvez donc pas définir un point de vue sur la mémoire. Si vous le pouviez, l'emplacement contiendrait 5. la taille de votre chaîne plus Terminator.


0 commentaires