IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Mauvais return ?


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Master Informatique seconde année
    Inscrit en
    Septembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Master Informatique seconde année
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2014
    Messages : 16
    Par défaut Mauvais return ?
    Bonjour à tous,

    Je ne suis pas du genre à poster des messages demandant de l'aide, mais ce problème me rend fou et j'ai rien trouvé d'interessant à propos de ça sur le net, alors je me tourne vers vous.
    Voici le problème :

    Dans une fonction, j'appelle mon strlen modifié qui compte les caractères d'un pointeur sur char jusqu'au \0.
    Seulement, lorsque je printf le return de ce strlen modifié, il affiche la mauvaise valeur.
    Exemple, je demande de compter combien il y a de caractères dans une chaîne qui fait 150 caractères ... la fonction me renverra une valeur négative, par exemple.
    La chose curieuse, c'est que ce strlen modif marche très bien pour les valeurs < 100, mais dès que ça commence à être un peu plus gros il déconne.
    Chose encore plus étonnante, si je printf la valeur avant de return, il a bien la valeur escomptée, même si la chaîne est supérieure à 100 caractères.

    Pour résumer et illuster, je vous fait un petit code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    int    main(void)
    {
       char *str = "chaine de 130 caractères";
       // dans l'exemple, c'est fait à l'arrache, mais cette chaîne est allouée et terminée par un \0 dans mon programme
       printf("%d\n", strlen_mod(str));
       return (0);
    }
    L'output correspondrait à -88, ou une valeur érronée, peu importe.

    Cependant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int   strlen_mod(char *str)
    {
    int   i = 0;
    while (str[i] != 0)
      i++;
    printf("%d\n", i);
    return (i);
    }
    Ce printf en revanche me donne la bonne valeur, il a bien compté jusqu'au bout...

    Des idées ? Je peux contourner en envoyant un pointeur sur int à la place de ce "i", et ça marche très bien, mais bon c'est chiant de pas pouvoir utiliser les valeurs de retour quoi.

    Merci d'avance. :3

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 476
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 476
    Par défaut
    Bonjour et bienvenue,

    En effet, c'est curieux. Ne voyant rien de flagrant dans ton exemple, je l'ai compilé et allongé la chaîne. J'obtiens de bons résultats dans tous les cas. Il doit donc s'agir d'un effet de bord.

    Ton programme est-il multi-threadé ? Généralement, ce genre de problème apparaît soit lorsque la chaîne n'est pas correctement terminée et que le curseur part s'enfoncer dans les tréfonds de la mémoire, soit lorsqu'il se fait écraser par un dépassement de tableau ou un écrasement de pile. Comme rien de tout cela ne peut se produire dans l'exemple concerné, peux-tu nous présenter le code exact et, si possible, en entier ?

    D'autre part, tu compiles sur quelle machine, avec quel système d'exploitation et quelle version de ton compilateur ?

    À part cela, sur la forme uniquement, les parenthèses après return sont inutiles. « return » n'est pas une fonction.

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Ton code d'exemple est valide.

    Par contre, si tu stocke le retour dans un char, ca peut se comprendre.

    Par ailleurs, ta fonction devrait prendre un char const * comme argument, permettant ainsi de l'appeler directement avec une chaine littérale.

  4. #4
    Membre averti
    Homme Profil pro
    Master Informatique seconde année
    Inscrit en
    Septembre 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Master Informatique seconde année
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2014
    Messages : 16
    Par défaut
    Re,

    Pour répondre au dernier message, je ne stocke pas dans un char, mais bien dans un int. (Pour pouvoir tester le retour, je printf("%d\n", strlen_mod(str));)

    Étant dans une école où les règles sont un peu spéciales (pour ne rien citer), vous envoyer le code serait long, et fastidieux pour vous à examiner (d'où les parenthèses sur le return etc etc).
    Mon programme n'est pas multithreadé, il s'agit d'un recode d'un shell simple avec les fonctions de base et quelques builtins.

    Je vais donc check toutes mes chaînes, voir si je met bien le \0 sur toutes, et je reviens vers vous si jamais ça plante encore. (dans l'immédiat je ne peux pas mais je vous tiens au courant le plus rapidement possible)

    Par ailleurs, je suis d'habitude sous OpenSUSE Dartmouth 12.3, mais je me suis installé une distrib Ubuntu Gnome à côté et c'est sur celle ci que je code. Elle est évidemment en LTS.
    Sinon, pour compiler, je fais ça "à la main" entre guillemets (emacs comme éditeur, gcc comme compilo, avec un makefile qui va bien, valgrind pour les leaks).

    Merci à vous !

    Edit : Fait curieux, un ami m'a fait remarquer qu'avec des chaînes de 127 caractères, ça marchait, mais pas 128. Pourtant, je ne store pas cette valeur dans un char, j'en suis sûr à 100%. (Quand je teste avec 128 et que je printf("%d => témoin\n", my_strlen(str)); l'output me donne : "-128 => témoin")

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ça ressemble pourtant vraiment à un retour en char, ça...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Voici un code minimal et compilable, qui marche chez moi (code::blocks 12.11):
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /*
    http://www.developpez.net/forums/d1469035/c-cpp/c/debuter/mauvais-return/#post7961192
    */
    #include <stdio.h>
     
    int strlen_mod(char const *str)
    {
    	int i = 0;
    	while(str[i] != 0)
    		i++;
    	printf("%d\n", i);
    	return (i);
    }
     
    int main(void)
    {
    	char const *str = "chaine de 130 caractères5678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
    	// dans l'exemple, c'est fait à l'arrache, mais cette chaîne est allouée et terminée par un \0 dans mon programme
    	printf("%d\n", strlen_mod(str));
    	return (0);
    }
    Que fait ce code chez toi?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    "127+1=-128" pour moi, c'est char (signed)
    bingo ... perdu!

    essaie "%ld"
    Ton makefile contient-il les options de compilation -Wall -Wextra?
    Si ce n'est pas le cas, ajoute les.

    Dans les deux cas, considère chaque warning comme une faute probable.
    un warning signifie "si tu as de la chance, ca peut marcher"

Discussions similaires

  1. [pl/pgSQL 7.2] Returns Opaque?
    Par Gruik dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 18/10/2003, 16h50
  2. return ();exit() ;
    Par Zazeglu dans le forum C
    Réponses: 12
    Dernier message: 10/10/2003, 20h56
  3. [C#] Changer le focus avec la touche return
    Par sblanc74 dans le forum Windows Forms
    Réponses: 6
    Dernier message: 01/10/2003, 18h38
  4. return
    Par drKzs dans le forum C
    Réponses: 3
    Dernier message: 18/09/2003, 22h36
  5. mauvais code
    Par moumou dans le forum Autres SGBD
    Réponses: 3
    Dernier message: 17/04/2003, 15h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo