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 :

Petit test qui tourne mal ..


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 4
    Par défaut Petit test qui tourne mal ..
    Hello Hello !
    Hier soir, en m'ennuyant je voulus faire un petit test pour m'amuser,
    essayer de "simuler" la classe String de C++. Mais bien sûr, comme d'habitude, quand je veux faire de petites choses.. POUF une erreur du coup je me rends encore compte de mon faible niveau ^^

    Donc du coup voilà le code:
    Code : 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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct _string
    {
      char *ch;
      size_t len;
    }String;
     
    String *
    create_string(char *str)
    {
      String *ptr = NULL;
     
      ptr->ch = malloc(sizeof(char) * strlen(str));
      strcpy(ptr->ch, str);
      ptr->len = strlen(ptr->ch);
     
      return ptr;
    }
     
    int
    main(void)
    {
      String *chaine = create_string("Saluuu");
     
      printf("chaine->str <---> %s\nchaine->len <---> %d\n", chaine->ch, chaine->len);
      return 0;
    }
    Et je mange un joli:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Erreur de segmentation (core dumped)
    Bon certes ce n'est pas l'erreur du siècle mais être bloqué par de si petites choses me fait savoir que je n'en sais pas assez et je stresse... Du coup j'ai valgrind et voilà le résultat:
    Code : 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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    ==5543== Memcheck, a memory error detector
    ==5543== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
    ==5543== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
    ==5543== Command: ./a.out
    ==5543== 
    ==5543== Invalid write of size 4
    ==5543==    at 0x804847E: create_string (in /home/lechienkitu/C/Test/a.out)
    ==5543==    by 0x80484D8: main (in /home/lechienkitu/C/Test/a.out)
    ==5543==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
    ==5543== 
    ==5543== 
    ==5543== Process terminating with default action of signal 11 (SIGSEGV)
    ==5543==  Access not within mapped region at address 0x0
    ==5543==    at 0x804847E: create_string (in /home/lechienkitu/C/Test/a.out)
    ==5543==    by 0x80484D8: main (in /home/lechienkitu/C/Test/a.out)
    ==5543==  If you believe this happened as a result of a stack
    ==5543==  overflow in your program's main thread (unlikely but
    ==5543==  possible), you can try to increase the size of the
    ==5543==  main thread stack using the --main-stacksize= flag.
    ==5543==  The main thread stack size used in this run was 8388608.
    ==5543== 
    ==5543== HEAP SUMMARY:
    ==5543==     in use at exit: 6 bytes in 1 blocks
    ==5543==   total heap usage: 1 allocs, 0 frees, 6 bytes allocated
    ==5543== 
    ==5543== LEAK SUMMARY:
    ==5543==    definitely lost: 6 bytes in 1 blocks
    ==5543==    indirectly lost: 0 bytes in 0 blocks
    ==5543==      possibly lost: 0 bytes in 0 blocks
    ==5543==    still reachable: 0 bytes in 0 blocks
    ==5543==         suppressed: 0 bytes in 0 blocks
    ==5543== Rerun with --leak-check=full to see details of leaked memory
    ==5543== 
    ==5543== For counts of detected and suppressed errors, rerun with: -v
    ==5543== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    Erreur de segmentation (core dumped)
    Donc je vois bien que mon erreur est au niveau de mon strcpy(), mais en quoi je foire ?

    Merci à vous.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    En déclarant ptr ainsi String *ptr, il te faut commencer par allouer l'espace qui va permettre de stocker ta structure String. Ici initialisant ptr à NULL, tu ne peux pas lui demander de fournir un champ ch.

    Attention aussi au fait que strlen ne retourne que le nombre de caractères sans le '\0' final. Il faut donc allouer strlen(str) + 1 Tu peux éviter de faire ce compte deux fois, en le stockant dans une variable.

    Et qui dit malloc, dit free lorsque tu as fini d'utiliser l'espace

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 4
    Par défaut
    Mais si je free() ça posera problème non ? Ensuite, enlever le NULL suffit il à "allouer" automatiquement la mémoire nécessaire ? (car je segfault quand même ...). Et pour finir, une petite question HS... (vais pas threader 10 fois):
    J'ai fait des tests avec strtok() et quand je fais char str[] = "blabla" no problème mais avec char *str = "blablabal", ça foire ... Why ?

    EDIT:
    Logiquement.. Je malloc ça alloue Oui donc maintenant ça marche.. Merci pour les éclaircissements à venir....

  4. #4
    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
    En gros, tu dois faire deux malloc(), à moins de faire ta classe de string autrement:
    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
    22
    23
    24
    25
    26
    #include <stddef.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct _string
    {
    	size_t len;
    	char ch[1];
    }String;
     
    String* create_string(char const *str)
    {
    	//Ce calcul facilite la possible future conversion du code pour wchar_t.
    	size_t cchLongueurChaine = strlen(str); //Longueur chaine en caractères
    	size_t cbTailleChaine = (cchLongueurChaine+1)*sizeof *str; //Taille (=longueur + carac nul) en bytes.
     
    	//Allocation de la structure
    	size_t tailleStructure = offsetof(String, ch) + cbTailleChaine;
    	String * ptr = malloc(tailleStructure);
    	if(ptr != NULL)
    	{
    		ptr->len = cchLongueurChaine;
    		strcpy(ptr->str, str);
    	}
    	return ptr;
    }
    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.

  5. #5
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Citation Envoyé par Geek0 Voir le message
    J'ai fait des tests avec strtok() et quand je fais char str[] = "blabla" no problème mais avec char *str = "blablabal", ça foire ... Why ?
    Bonjour,
    1. strtok modifie la chaine que tu lui donnes.
    2. une chaine littérale ("blabla" par exemple) est stockée dans une zone mémoire en read-only.
    3. char str[] = "blabla" : crée un tableau de char et copie la valeur pointée par "blabla" dans le tableau. Tu peux modifier str, donc tu peux l'utiliser avec strtok
    4. char* str = "blabla" : le pointeur str pointe vers "blabla" qui est dans une zone mémoire read-only que tu ne peux pas modifier : tu ne peux pas le passer en paramètre à strtok car strtok va essayer de le modifier.

    Voilà

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 4
    Par défaut
    Et la lumière fut... Merci beaucoup !
    De votre mérite un second Stallman naîtra...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 22
    Dernier message: 21/10/2013, 14h25
  2. augmentation qui tourne mal
    Par digger dans le forum Contrat
    Réponses: 2
    Dernier message: 14/06/2012, 08h51
  3. [MySQL] interprétation requete qui tourne mal
    Par efrbeldin dans le forum PHP & Base de données
    Réponses: 10
    Dernier message: 06/10/2011, 02h02
  4. Réponses: 2
    Dernier message: 23/04/2006, 21h02

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