Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2518 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Comportement surprenant de strcpy

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Comportement surprenant de strcpy

n°1859546
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 21:52:15  profilanswer
 

Attention, question piège spécial experts.

 

Voici un programme tout con.
Si je compile (gcc 4)

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(int argc, char *argv[])
  4. {
  5.     char src[] = "abcdefghijklmnopqrstuvwxyz0123456789";
  6.     char dst[sizeof(src)] = "";
  7.     printf("sizeof src %d, sizeof dst %d\n", sizeof(src), sizeof(dst));
  8.     strcpy(dst, src);
  9.     printf("src %s %d\ndst %s %d\n", src, strlen(src), dst, strlen(dst));
  10.     return 0;
  11. }
 

Ca me sort:

 

sizeof src 37, sizeof dst 37
src abcdefghijklmnopqrstuvwxyz0123456789 36
dst abcdefghijklmnopqrstuvwxyz0123456789 36

 

Normal.

 

Maintenant, si je remplace la ligne 8 par
    char dst[sizeof(src)-1] = "";

 

A votre avis, que se passe-t'il à l'exécution ? Que me sort valgrind ?

 

Même question si je remplace la ligne par
    char dst[sizeof(src)-2] = "";

 

Appelez-moi noob, mais le résultat est tout de même assez surprenant.

Message cité 3 fois
Message édité par el muchacho le 09-03-2009 à 22:00:37

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
mood
Publicité
Posté le 09-03-2009 à 21:52:15  profilanswer
 

n°1859548
sligor
Posté le 09-03-2009 à 21:55:06  profilanswer
 

tu as oublié d'enlever le "-2" après le sizeof dans ton code :o

Message cité 1 fois
Message édité par sligor le 09-03-2009 à 21:55:26
n°1859549
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 21:56:32  profilanswer
 

Sur ma plateforme (Linux x86), pour le premier cas, j'ai ceci:

 
Citation :

sizeof src 37, sizeof dst 36
src abcdefghijklmnopqrstuvwxyz0123456789 36
dst abcdefghijklmnopqrstuvwxyz0123456789 36

 

De plus, valgrind n'indique aucune erreur !

 

Dans le second cas, valgrind n'indique toujours aucune erreur !!!
Par contre, le runtime détecte une corruption de la pile.

 

J'ai exactement ceci:

 
Citation :


gromit:~/dev/SPString$ valgrind ./a.out
==6659== Memcheck, a memory error detector.
==6659== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==6659== Using LibVEX rev 1884, a library for dynamic binary translation.
==6659== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==6659== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==6659== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==6659== For more details, rerun with: -v
==6659==
sizeof src 37, sizeof dst 35
src abcdefghijklmnopqrstuvwxyz0123456789 36
dst abcdefghijklmnopqrstuvwxyz0123456789 36
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0x41326d8]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0x4132690]
./a.out[0x80485d5]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0x404e685]
./a.out[0x80483f1]
======= Memory map: ========
04000000-0401a000 r-xp 00000000 08:21 4562977    /lib/ld-2.8.90.so
0401a000-0401b000 rw-p 0401a000 00:00 0
0401b000-0401c000 r--p 0001a000 08:21 4562977    /lib/ld-2.8.90.so
0401c000-0401d000 rw-p 0001b000 08:21 4562977    /lib/ld-2.8.90.so
0401d000-0401f000 rw-p 0401d000 00:00 0
0401f000-04020000 r-xp 00000000 08:21 4195119    /usr/local/lib/valgrind/x86-linux/vgpreload_core.so
04020000-04021000 r--p 00000000 08:21 4195119    /usr/local/lib/valgrind/x86-linux/vgpreload_core.so
04021000-04022000 rw-p 00001000 08:21 4195119    /usr/local/lib/valgrind/x86-linux/vgpreload_core.so
04022000-04029000 r-xp 00000000 08:21 4195138    /usr/local/lib/valgrind/x86-linux/vgpreload_memcheck.so
04029000-0402a000 r--p 00006000 08:21 4195138    /usr/local/lib/valgrind/x86-linux/vgpreload_memcheck.so
0402a000-0402b000 rw-p 00007000 08:21 4195138    /usr/local/lib/valgrind/x86-linux/vgpreload_memcheck.so
0402b000-0402c000 rw-p 0402b000 00:00 0
04038000-04190000 r-xp 00000000 08:21 4580349    /lib/tls/i686/cmov/libc-2.8.90.so
04190000-04192000 r--p 00158000 08:21 4580349    /lib/tls/i686/cmov/libc-2.8.90.so
04192000-04193000 rw-p 0015a000 08:21 4580349    /lib/tls/i686/cmov/libc-2.8.90.so
04193000-04196000 rw-p 04193000 00:00 0
041a3000-045a3000 rwxp 041a3000 00:00 0
045a3000-045b0000 r-xp 00000000 08:21 4562955    /lib/libgcc_s.so.1
045b0000-045b1000 r--p 0000c000 08:21 4562955    /lib/libgcc_s.so.1
045b1000-045b2000 rw-p 0000d000 08:21 4562955    /lib/libgcc_s.so.1
08048000-08049000 r-xp 00000000 08:21 4456618    /home/nicolas/dev/SPString/a.out
08049000-0804a000 r--p 00000000 08:21 4456618    /home/nicolas/dev/SPString/a.out
0804a000-0804b000 rw-p 00001000 08:21 4456618    /home/nicolas/dev/SPString/a.out
0804b000-0804c000 rwxp 0804b000 00:00 0
38000000-381c3000 r-xp 00000000 08:21 4195137    /usr/local/lib/valgrind/x86-linux/memcheck
381c4000-381c5000 rw-p 001c3000 08:21 4195137    /usr/local/lib/valgrind/x86-linux/memcheck
381c5000-388e3000 rw-p 381c5000 00:00 0
61fa2000-62b22000 rwxp 61fa2000 00:00 0
62b22000-62b24000 ---p 62b22000 00:00 0
62b24000-62b34000 rwxp 62b24000 00:00 0
62b34000-62b36000 ---p 62b34000 00:00 0
62b36000-64c93000 rwxp 62b36000 00:00 0
b8043000-b8044000 r-xp b8043000 00:00 0          [vdso]
bef41000-bef43000 rwxp bef41000 00:00 0
bff2f000-bff44000 rw-p bffeb000 00:00 0          [stack]
==6659==
==6659== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 14 from 2)
==6659== malloc/free: in use at exit: 0 bytes in 0 blocks.
==6659== malloc/free: 5 allocs, 5 frees, 908 bytes allocated.
==6659== For counts of detected errors, rerun with: -v
==6659== All heap blocks were freed -- no leaks are possible.
Aborted

 

Je n'arrive pas trop à m'expliquer ce comportement.


Message édité par el muchacho le 09-03-2009 à 23:14:51

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859550
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 21:59:41  profilanswer
 

sligor a écrit :

tu as oublié d'enlever le "-2" après le sizeof dans ton code :o


Oups, corrigé.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859551
sligor
Posté le 09-03-2009 à 22:05:47  profilanswer
 

moi dans le "-1" j'ai:

Citation :

sizeof src 37, sizeof dst 36
src  0
dst abcdefghijklmnopqrstuvwxyz0123456789 36

 

valgrind râle:

Citation :


==13532== Source and destination overlap in strcpy(0xBEFDE4E7, 0xBEFDE50B)
==13532==    at 0x402457D: strcpy (mc_replace_strmem.c:268)
==13532==    by 0x80484D6: main (test.c:11)

 

et dans le "-2" j'ai:

Citation :


./a.out
sizeof src 37, sizeof dst 35
src 9 1
dst abcdefghijklmnopqrstuvwxyz0123456789 36

 

valgrind râle:

Citation :


==13553== Source and destination overlap in strcpy(0xBEB114E8, 0xBEB1150B)
==13553==    at 0x402457D: strcpy (mc_replace_strmem.c:268)
==13553==    by 0x80484F1: main (test.c:11)

 

chez moi c'est beaucoup plus compréhensible  :D

 

je dirais que dans ta pile src et dst sont inversés par rapport à la mienne

 

edit: tu peux essayer de rajouter printf("dst-src=%d\n",dst-src); pour voir ?

Message cité 1 fois
Message édité par sligor le 09-03-2009 à 22:07:51
n°1859552
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:08:44  profilanswer
 

Euh, c'est bien le même programme, là ? Parce que l'overlap, je vois vraiment pas pourquoi [:pingouino]


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859553
sligor
Posté le 09-03-2009 à 22:11:56  profilanswer
 

el muchacho a écrit :

Euh, c'est bien le même programme, là ? Parce que l'overlap, je vois vraiment pas pourquoi [:pingouino]


si dst est juste avant src dans la pile, ce qui est le cas chez moi

Message cité 1 fois
Message édité par sligor le 09-03-2009 à 22:12:22
n°1859554
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:12:58  profilanswer
 

sligor a écrit :


edit: tu peux essayer de rajouter printf("dst-src=%d\n",dst-src); pour voir ?


Code :
  1. ...
  2. printf("dst-src=%d\n",dst-src);
  3. strcpy(dst, src);
  4. printf("dst-src=%d\n",dst-src);
  5. ...


 
Résultat:
dst-src=-37
dst-src=-37
(résultat attendu)


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859555
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:14:21  profilanswer
 

sligor a écrit :


si dst est juste avant src dans la pile, ce qui est le cas chez moi


Ah oui, ok, pas con. C'est quoi, ta machine, à titre indicatif ?


Message édité par el muchacho le 09-03-2009 à 22:15:38

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859556
sligor
Posté le 09-03-2009 à 22:19:06  profilanswer
 

el muchacho a écrit :


Code :
  1. ...
  2. printf("dst-src=%d\n",dst-src);
  3. strcpy(dst, src);
  4. printf("dst-src=%d\n",dst-src);
  5. ...
 

Résultat:
dst-src=-37
dst-src=-37
(résultat attendu)


donc tu as aussi dst avant src, tu as la même organisation de pile que moi, du coup je ne comprends pas pourquoi tu n'as pas 0 et 1 comme longueur de dst avec "-1" et "-2", à moins que le compilateur change l'organisation sur les autres valeurs.
Tu peux aussi tester avec les "-1" et "-2" ?

 

ma config: debian lenny, gcc 4.3.2, x86 32bits

Message cité 1 fois
Message édité par sligor le 09-03-2009 à 22:20:03
mood
Publicité
Posté le 09-03-2009 à 22:19:06  profilanswer
 

n°1859557
Taz
bisounours-codeur
Posté le 09-03-2009 à 22:20:07  profilanswer
 

Y a quoi de surprenant dans un UB ?

n°1859558
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:22:06  profilanswer
 

sligor a écrit :


ma config: debian lenny, gcc 4.3.2, x86 32bits


J'ai la même version de gcc que toi, sous Ubuntu.

Citation :

Tu peux aussi tester avec les "-1" et "-2" ?


J'obtiens la même chose qu'avant.

Taz a écrit :

Y a quoi de surprenant dans un UB ?


Un quoi ??


Message édité par el muchacho le 09-03-2009 à 22:24:42

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859561
Gf4x3443
Killing perfection
Posté le 09-03-2009 à 22:34:01  profilanswer
 

el muchacho a écrit :


A votre avis, que se passe-t'il à l'exécution ?

 

Tu altères la pile, et le résultat est "indéfini" (dépendant de comment le compilateur va optimiser le code, l'ordre des variables, et probablement l'architecture aussi). Le seul moyen de vraiment en être sur, c'est de regarder le code compilé.

 
el muchacho a écrit :

Que me sort valgrind ?

 

Valgrind a beaucoup de mal à détecter le petage de pile, vu qu'il ne fait pas de bound checking sur des agrégats en pile ou statique.

 

C'est particulièrement difficile à détecter de toute manière, il n'y a pas autant de liberté que dans le tas ou on peut facilement placer des tokens ou des pages invalides pour provoquer des fautes d'accès.

 

Ce cas là de toute manière, tu peux l'empecher avec des canary. Compile avec -fstack-protector...

Message cité 2 fois
Message édité par Gf4x3443 le 09-03-2009 à 22:34:53

---------------
Petit guide Kerberos pour l'administrateur pressé
n°1859562
Elmoricq
Modérateur
Posté le 09-03-2009 à 22:35:45  profilanswer
 

el muchacho a écrit :

Attention, question piège spécial experts.

 

Voici un programme tout con.
Si je compile (gcc 4)

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(int argc, char *argv[])
  4. {
  5.     char src[] = "abcdefghijklmnopqrstuvwxyz0123456789";
  6.     char dst[sizeof(src)] = "";
  7.     printf("sizeof src %d, sizeof dst %d\n", sizeof(src), sizeof(dst));
  8.     strcpy(dst, src);
  9.     printf("src %s %d\ndst %s %d\n", src, strlen(src), dst, strlen(dst));
  10.     return 0;
  11. }
 

Ca me sort:

 

sizeof src 37, sizeof dst 37
src abcdefghijklmnopqrstuvwxyz0123456789 36
dst abcdefghijklmnopqrstuvwxyz0123456789 36

 

Normal.

 

Maintenant, si je remplace la ligne 8 par
    char dst[sizeof(src)-1] = "";

 

A votre avis, que se passe-t'il à l'exécution ? Que me sort valgrind ?

 

Même question si je remplace la ligne par
    char dst[sizeof(src)-2] = "";

 

Appelez-moi noob, mais le résultat est tout de même assez surprenant.

 

Rien de surprenant.

 

Les deux résultats sont identiques avec -1 et -2 (aléatoirement), et valgrind devrait te sortir un truc du genre "read out of bound" ou ce genre de chose.

 

strcpy() recopie src dans dst jusqu'à trouver un '\0'. Sans se préoccuper de la taille de dst. Donc ça recopie src dans dst en dépassant les capacités de cette dernière variable.

 

edit : ah ok j'avais pas lu la suite, et je me serais attendu aussi à ce que valgrind râle. Oubliez mon post qui arrive comme un cheveu sur la soupe. [:prozac]


Message édité par Elmoricq le 09-03-2009 à 22:37:13
n°1859563
sligor
Posté le 09-03-2009 à 22:36:49  profilanswer
 

Gf4x3443 a écrit :

 

Tu altères la pile, et le résultat est "indéfini" (dépendant de comment le compilateur va optimiser le code, l'ordre des variables, et probablement l'architecture aussi). Le seul moyen de vraiment en être sur, c'est de regarder le code compilé.

 



sauf que si dst-src=-37 il ne peut pas péter la pile avec ce qu'il fait  :o
donc j'aimerais bien qu'il revérifie avec sizeof(src)-1 et sizeof(src)-2  :o

Message cité 1 fois
Message édité par sligor le 09-03-2009 à 22:49:50
n°1859564
Taz
bisounours-codeur
Posté le 09-03-2009 à 22:37:05  profilanswer
 

Undefined Behaviour

n°1859567
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:42:25  profilanswer
 

Gf4x3443 a écrit :


Tu altères la pile, et le résultat est "indéfini" (dépendant de comment le compilateur va optimiser le code, l'ordre des variables, et probablement l'architecture aussi). Le seul moyen de vraiment en être sur, c'est de regarder le code compilé.


:jap:

 
Citation :

Valgrind a beaucoup de mal à détecter le petage de pile, vu qu'il ne fait pas de bound checking sur des agrégats en pile ou statique.

 

C'est particulièrement difficile à détecter de toute manière, il n'y a pas autant de liberté que dans le tas ou on peut facilement placer des tokens ou des pages invalides pour provoquer des fautes d'accès.


C'est ce que je me disais aussi.

 
Citation :

Ce cas là de toute manière, tu peux l'empecher avec des canary. Compile avec -fstack-protector...


:jap: je vais essayer ça.

Taz a écrit :

Undefined Behaviour


OK.

sligor a écrit :


sauf que si dst-src=-37 il ne peut pas péter la pile avec ce qu'il fait  :o
donc j'aimerais bien qui revérifie avec sizeof(src)-1 et sizeof(src)-2  :o


J'ai 37 à chaque fois, et j'ai la même chose qu'auparavant pour le reste du code.
Et par ailleurs, j'ai la même version de gcc que toi.


Message édité par el muchacho le 09-03-2009 à 22:46:48

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859569
tpierron
Posté le 09-03-2009 à 22:45:19  profilanswer
 

Ah ouais, tiens, dans le même genre. Qu'est ce qu'il y a de foireux avec ce code :
 

Code :
  1. char version[4];
  2. if (sscanf("1.9.0.2", "%hhu.%hhu.%hhu.%hhu", version, version+1, version+2, version+3) == 4)
  3. {
  4.     // Plantage probable.
  5. }


Spoiler :

En fait il n'y a rien de vraiment faux dans ce code.
 
Par contre sous Windows, avec certaine version de la msvcrt le %hhu est interprété comme un %u. Dans ce cas là, dès le "version+1", il y stack overflow. Je suis bouffé des plantages complètement aléatoires dans des portions de codes à des kilomètres de l'erreur, avec une compilation en -O2 ou -O3 sous MinGW, alors qu'en -O0, ça passait sans le moindre problème.
 
Une demi journée de débuguage  :sweat:

n°1859571
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:49:04  profilanswer
 

Ah putaing, cong, en fait, sligor a raison : avec le -1, j'ai +37 ! gcc change l'ordre des chaînes dans la pile !


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859574
sligor
Posté le 09-03-2009 à 22:51:13  profilanswer
 

donc du coup la corruption de pile est plus logique, tout s'explique :jap:

n°1859575
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:52:15  profilanswer
 
n°1859576
Gf4x3443
Killing perfection
Posté le 09-03-2009 à 22:52:35  profilanswer
 

tpierron a écrit :

Ah ouais, tiens, dans le même genre. Qu'est ce qu'il y a de foireux avec ce code :
Une demi journée de débuguage  :sweat:

 

Ayé, je compatis. J'ai eu aussi des problèmes avec des LARGE_INTEGER avec MinGW. Je me rappelle avoir passé ma semaine à essayer de comprendre pourquoi je n'avais pas de bonnes valeurs affichées dans des printf().

 

En fait, c'est là tout le challenge: entre un code source et le code compilé, c'est non trivial de qualifier du code aujourd'hui. Enfin du moins, dans de l'embarqué, ca m'a valu quelques crises :/

Message cité 1 fois
Message édité par Gf4x3443 le 09-03-2009 à 22:53:03

---------------
Petit guide Kerberos pour l'administrateur pressé
n°1859577
Elmoricq
Modérateur
Posté le 09-03-2009 à 22:53:16  profilanswer
 

tpierron a écrit :

Ah ouais, tiens, dans le même genre. Qu'est ce qu'il y a de foireux avec ce code :

 
Code :
  1. char version[4];
  2. if (sscanf("1.9.0.2", "%hhu.%hhu.%hhu.%hhu", version, version+1, version+2, version+3) == 4)
  3. {
  4.     // Plantage probable.
  5. }


Spoiler :

En fait il n'y a rien de vraiment faux dans ce code.

 

Par contre sous Windows, avec certaine version de la msvcrt le %hhu est interprété comme un %u. Dans ce cas là, dès le "version+1", il y stack overflow. Je suis bouffé des plantages complètement aléatoires dans des portions de codes à des kilomètres de l'erreur, avec une compilation en -O2 ou -O3 sous MinGW, alors qu'en -O0, ça passait sans le moindre problème.

 

Une demi journée de débuguage  :sweat:


 

Hm. C'est pas un problème de norme plutôt ? Je zone les manpages depuis 5min, et il y en a avec hh, et d'autres sans.
Pour rire j'ai regardé sur Solaris 8 (ok, côté norme c'est pas ce qu'il y a de plus strict cet OS :/ ), pas de hh. Sur Solaris 10 par contre, il y est.

 

edit : trouvé. "hh" c'est bien C99, d'où les différences de comportement avec certains compilateurs pas à jour.

Message cité 1 fois
Message édité par Elmoricq le 09-03-2009 à 22:57:16
n°1859578
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:53:40  profilanswer
 

Sinon, le -fstack-protector, j'ai pas trop vu son effet. :/


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859579
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 22:57:21  profilanswer
 

Gf4x3443 a écrit :


Ayé, je compatis. J'ai eu aussi des problèmes avec des LARGE_INTEGER avec MinGW. Je me rappelle avoir passé ma semaine à essayer de comprendre pourquoi je n'avais pas de bonnes valeurs affichées dans des printf().
 
En fait, c'est là tout le challenge: entre un code source et le code compilé, c'est non trivial de qualifier du code aujourd'hui. Enfin du moins, dans de l'embarqué, ca m'a valu quelques crises :/


Clair, ce qu'il y a de bien avec le C, c'est que c'est supêr simple, mais on peut passer une vie entière sur ce genre de conneries.:/


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859580
sligor
Posté le 09-03-2009 à 22:57:22  profilanswer
 

Elmoricq a écrit :

 

Hm. C'est pas un problème de norme plutôt ? Je zone les manpages depuis 5min, et il y en a avec hh, et d'autres sans.
Pour rire j'ai regardé sur Solaris 8 (ok, côté norme c'est pas ce qu'il y a de plus strict cet OS :/ ), pas de hh. Sur Solaris 10 par contre, il y est.


d'où l'utilité de l'option "-pedantics" avec gcc
mais sur un gros projet développé sans cette option dés le dépat, on a vite d'innombrables warnings

Citation :


 gcc -g test.c -Wall -ansi -pedantic
test.c: In function ‘main’:
test.c:7: warning: ISO C90 does not support the ‘hh’ scanf length modifier
test.c:7: warning: format ‘%hhu’ expects type ‘unsigned char *’, but argument 3 has type ‘char *’
test.c:7: warning: ISO C90 does not support the ‘hh’ scanf length modifier
test.c:7: warning: format ‘%hhu’ expects type ‘unsigned char *’, but argument 4 has type ‘char *’
test.c:7: warning: ISO C90 does not support the ‘hh’ scanf length modifier
test.c:7: warning: format ‘%hhu’ expects type ‘unsigned char *’, but argument 5 has type ‘char *’
test.c:7: warning: ISO C90 does not support the ‘hh’ scanf length modifier
test.c:7: warning: format ‘%hhu’ expects type ‘unsigned char *’, but argument 6 has type ‘char *’



Message édité par sligor le 09-03-2009 à 22:58:42
n°1859581
Elmoricq
Modérateur
Posté le 09-03-2009 à 22:57:51  profilanswer
 

J'ai édité mon post 4s avant ta réponse. [:klem3i1]

n°1859586
Gf4x3443
Killing perfection
Posté le 09-03-2009 à 23:02:28  profilanswer
 

Il n'aborte pas avec -1?
 

toulouse$ grep "dst" test.c              
    char dst[sizeof(src) - 1] = "";
    printf("sizeof src %d, sizeof dst %d\n", sizeof(src), sizeof(dst));
    strcpy(dst, src);
    printf("src %s %d\ndst %s %d\n", src, strlen(src), dst, strlen(dst));
toulouse$ cc -fstack-protector -o test test.c    
toulouse$ ./test                                                                
sizeof src 37, sizeof dst 36
src abcdefghijklmnopqrstuvwxyz0123456789 36
dst abcdefghijklmnopqrstuvwxyz0123456789 36
Program received signal SIGABRT, Aborted.


---------------
Petit guide Kerberos pour l'administrateur pressé
n°1859592
sligor
Posté le 09-03-2009 à 23:06:14  profilanswer
 

c'est indéterminé ça dépends de plein de choses, on était plus parti pour comprendre ce qu'il se passait plus exactement sur la machine de el muchacho


Message édité par sligor le 09-03-2009 à 23:06:33
n°1859593
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 23:08:46  profilanswer
 

Chez moi, il n'en a rien à secouer. Je suppose que c'est exactement pour la même raison qu'au-dessus, à savoir que l'ordre des chaînes sur la pile est bizarrement inversé quand je réduis la taille de dst. Ce qui est bizarre, c'est que gcc se comporte comme ça que chez moi (avec les options de compilation par défaut).


Message édité par el muchacho le 09-03-2009 à 23:09:53

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859598
Gf4x3443
Killing perfection
Posté le 09-03-2009 à 23:10:35  profilanswer
 

Ca c'est fun. C'est quelle version 4 de gcc? 4.1.2 ici (sous NetBSD), pas d'inversion dans les adresses des tableaux, ca fait -37, -36, -35, ... quand je réduis dst.


Message édité par Gf4x3443 le 09-03-2009 à 23:11:48

---------------
Petit guide Kerberos pour l'administrateur pressé
n°1859600
el muchach​o
Comfortably Numb
Posté le 09-03-2009 à 23:14:20  profilanswer
 

Citation :

gromit:~/dev/SPString$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)


 
Le plus marrant, c'est que c'est le même compilo que sligor, et chez lui, il n'obitent pas la même chose.
sligor, ça donne quoi, chez toi
gcc -v  
?


Message édité par el muchacho le 09-03-2009 à 23:17:03

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°1859649
Emmanuel D​elahaye
C is a sharp tool
Posté le 10-03-2009 à 08:24:39  profilanswer
 

el muchacho a écrit :

Attention, question piège spécial experts.
 
Voici un programme tout con.
Si je compile (gcc 4)

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(int argc, char *argv[])
  4. {
  5.     char src[] = "abcdefghijklmnopqrstuvwxyz0123456789";
  6.     char dst[sizeof(src)] = "";
  7.     printf("sizeof src %d, sizeof dst %d\n", sizeof(src), sizeof(dst));
  8.     strcpy(dst, src);
  9.     printf("src %s %d\ndst %s %d\n", src, strlen(src), dst, strlen(dst));
  10.     return 0;
  11. }


 
Ca me sort:
 
sizeof src 37, sizeof dst 37
src abcdefghijklmnopqrstuvwxyz0123456789 36
dst abcdefghijklmnopqrstuvwxyz0123456789 36
 
Normal.
 
Maintenant, si je remplace la ligne 8 par
    char dst[sizeof(src)-1] = "";


Le comportement est indéfini. tout peut arriver.
 

Citation :

A votre avis, que se passe-t'il à l'exécution ? Que me sort valgrind ?


Personne ne peut le prévoir. Mais le code est faux, c'est certain.

Citation :


Même question si je remplace la ligne par  
    char dst[sizeof(src)-2] = "";
 
Appelez-moi noob, mais le résultat est tout de même assez surprenant.


Je ne sais pas de quel résultat tu parles, mais on a pas à s'étonner d'un comportement indéfini. Je répète TOUT peut arriver, y compris un comportement d'apparence normale.
 
Un code est correct si
 
1 - il est écrit correctement
2 - il se comporte comme prévu.
 
Si le #1 est faux tout le reste est sans objet.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1859651
Emmanuel D​elahaye
C is a sharp tool
Posté le 10-03-2009 à 08:32:29  profilanswer
 

tpierron a écrit :

En fait il n'y a rien de vraiment faux dans ce code.
 
Par contre sous Windows, avec certaine version de la msvcrt<...>


C'est pas un problème de codage, mais de bibliothèque C sous Windows qui, rappelons le une bonne fois pour toute : ne supporte pas C99...  
(même si certaines concessions semblent avoir été faites sous Vista SP1, comme le support de "%ll*" )


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1860068
tpierron
Posté le 10-03-2009 à 22:06:43  profilanswer
 

Emmanuel Delahaye a écrit :


C'est pas un problème de codage, mais de bibliothèque C sous Windows qui, rappelons le une bonne fois pour toute : ne supporte pas C99...  
(même si certaines concessions semblent avoir été faites sous Vista SP1, comme le support de "%ll*" )

Le pire c'est que j'avais fait un test rapide pour voir si ça fonctionnait. Comme l'ordre des octets était little-endian, la seule chose qui merdait était le stack overflow (que je n'avais pas pensé à vérifié dans mon test). En big endian, j'aurais vu directement le problème, puisque tout aurait valu 0 (vu que je convertissais des nombres < 10). En fait, le comportement que j'attendais était que le code de retour reflète les formats de conversion non reconnu, jamais j'aurais imaginé que cette lib puisse écrire un int dans un char :/.

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Comportement surprenant de strcpy

 

Sujets relatifs
Sémaphore Posix anonyme - comportement inexpliquéComportement étrange avec IE / Firefox OK
[PHP][résolu] Include et global -- comportement étrange --[Plone] Customisation du comportement d'un lien
Debug d'ASP.net : Comportement de Visual Studio et IISshmget: comportement que je ne comprends pas
Comportement d'une boucle sur un tableau modifié dans la boucle[C++] comportement GCC
Comportement des stringComportement bizarre sous IE7 => bug?
Plus de sujets relatifs à : Comportement surprenant de strcpy


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR