Faire un don ! | | style | statistiques | contactez-nous | plan | lettre d'information

Retourner aux forums || Retourner au forum Programmation.c

Programmation.c : Structures...

Posté par mansuetus (page perso, ) le 15 septembre 2004
Je suis tout newb en C, et j'aimerais comprendre comment marchent les satanées structures.

rien ne vaut un bon exemple...
--------------- début du code ----------------

struct structure {
char * a;
char * b;
char * c;
};

#include <stdio.h>

struct structure *wazaa ( )
{
struct structure *to_ret;
to_ret->a = malloc (20*sizeof(char));
to_ret->a = "aaa";
to_ret->b = malloc (20*sizeof(char));
to_ret->b = "bbb";
to_ret->c = malloc (20*sizeof(char));
to_ret->c = "ccc";
return(to_ret);
}

int print_struct ( struct structure *aa )
{
printf ("%s--%s--%s\n", aa->a, aa->b, aa->c);
return (0);
}


int main (void)
{
struct structure *test;
test->a = "a non initialise";
test->b = "b non initialise";
test->c = "c non initialise";

print_struct ( test );
test = wazaa ();
print_struct ( test );
return (0);
}

--------------- Fin du code -------------------

exécution :
----
a non initialise--b non initialise--c non initialise
Erreur de segmentation
----

mon but est d'obtenir un PAS segfault, pour comprendre où et comment allouer de la mémoire aux structures contenant des pointeurs. (car j'ai un petit projet qui bloque dessus depuis 5 jours et ça commence à me les &&##@$$ menues.

merci pour votre aide. (et même si mon projet ne se débloque pas grace à ce post, je me coucherai au moins moins con !)

--
mansuetus @ spontex . org
> Lire le message (22 commentaires, moyenne: 1,8).  

Cette discussion est archivée, il n'est plus possible de laisser des commentaires.

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.

malloc

Posté par Me Nut (page perso, ) le 15/09/2004 à 09:18. (lien). Évalué à 1.

Dans ton main il faut allouer de la mémoire à test :
struct structure *test = malloc( 60 * sizeof( char ));
au lieu de
struct structure *test;

--
"On the internet, nobody can hear you being subtle" -- /usr/src/linux/Documentation/ManagementStyle
  • [^]On progresse... mais c'est pas encore gagné...

    Posté par mansuetus (page perso, ) le 15/09/2004 à 09:24. (lien). Évalué à 1.

    --- après modifs : ---


    int main (void)
    {
    struct structure *test = malloc (60*sizeof(char));
    test->a = "a non initialise";
    test->b = "b non initialise";
    test->c = "c non initialise";

    print_struct ( test );
    test = wazaa ();
    print_struct ( test );
    return (0);
    }

    ---------------------------

    a non initialise--b non initialise--c non initialise
    aaa--bbb--ccc
    Erreur de segmentation

    mais là, GDB m'aide pas trop :
    ---------
    Program received signal SIGSEGV, Segmentation fault.
    _dl_fini () at dl-fini.c:64
    64 dl-fini.c: Aucun fichier ou répertoire de ce type.
    in dl-fini.c
    ---------
    je n'ai aucune idée de ce qu'est ce zouf ! c quoi cette affaire de dl-fini.c ? faut recompiler la glibc ?

    essayons hello world :
    --------------------------------------
    #include <stdio.h>

    int main (void)
    {
    printf ("hello world\n");
    return (0);
    }
    --------------------------------------
    mansuetus@spontexserver:~/Prog/petits_softs/tests$ ./hello
    hello world
    mansuetus@spontexserver:~/Prog/petits_softs/tests$
    ---------------------------------------


    Je ne comprends plus rien ... mais ça, c'est pas nouveau !

    --
    mansuetus @ spontex . org
    • [^]Re: On progresse... mais c'est pas encore gagné...

      Posté par Me Nut (page perso, ) le 15/09/2004 à 09:31. (lien). Évalué à 2.

      chezmoicamarche.

      version de gcc ? chez moi 3.4.2

      void wazaa ( struct structure *sss )
      {
      sss->a = "aaa";
      sss->b = "bbb";
      sss->c = "ccc";
      }

      int main ( void )
      {

      struct structure *test;
      test = malloc ( sizeof ( struct structure ) );
      test->a = malloc ( 20 * sizeof ( char ) );
      test->b = malloc ( 20 * sizeof ( char ) );
      test->c = malloc ( 20 * sizeof ( char ) );

      test->a = "a non initialise";

      test->b = "b non initialise";

      test->c = "c non initialise";

      print_struct ( test );

      wazaa ( test );

      print_struct ( test );

      return ( 0 );

      }

      --
      "On the internet, nobody can hear you being subtle" -- /usr/src/linux/Documentation/ManagementStyle
      • [^]Re: On progresse... mais c'est pas encore gagné...

        Posté par FReEDoM (page perso, ) le 15/09/2004 à 09:35. (lien). Évalué à 2.

        coup de bol

        Je persiste à dire que
        sss->a = "aaa";
        sss->b = "bbb";
        sss->c = "ccc";

        Fait pointer sss->a sur la pile, si la pile reste tout va bien si le programme la modifie à cette endroit rien ne va plus.

        En gros si tu appelle 2 ou 3 fonction entre wazaa() et print_struct(), ton programme ne marchera plus.

    • [^]Re: On progresse... mais c'est pas encore gagné...

      Posté par mansuetus (page perso, ) le 15/09/2004 à 09:33. (lien). Évalué à 0.

      EDIT OULA !!

      en fait, ça marche, je me suis gourré en modifiant...

      merci !

      --
      mansuetus @ spontex . org

Petite erreur

Posté par alberthier (page perso, ) le 15/09/2004 à 09:19. (lien). Évalué à 2.

la structure que tu renvoie n'a pas de mémoire allouée : tu déclares un pointeur et tu l'utilise sans lui allouer de mémoire.

struct structure *wazaa ( )
{
struct structure *to_ret;
to_ret = malloc(sizeof(struct structure));
to_ret->a = malloc (20*sizeof(char));
to_ret->a = "aaa";
to_ret->b = malloc (20*sizeof(char));
to_ret->b = "bbb";
to_ret->c = malloc (20*sizeof(char));
to_ret->c = "ccc";
return(to_ret);
}

  • [^]Re: Petite erreur

    Posté par alberthier (page perso, ) le 15/09/2004 à 09:24. (lien). Évalué à 2.

    J'ai lu un peu vite.
    Comme dis plus haut , il faut que tu alloue de la mémoire pour test dans ton main :

    test = malloc(sizeof(struct structure));
    test->a = malloc (20*sizeof(char));
    test->b = malloc (20*sizeof(char));
    test->c = malloc (20*sizeof(char));

    et écris ta fonction wasaa comme ca :

    void wazaa (struct structure * sss)
    {
    sss->a = "aaa";
    sss->b = "bbb";
    sss->c = "ccc";
    }

    • [^]Re: Petite erreur

      Posté par kesako () le 15/09/2004 à 09:34. (lien). Évalué à 5.

      non , toi non plus tu n'as pas compris

      ce sont des POINTEURS

      quand vous faites
      char * P = malloc (...)

      P est un pointeur ( c'est a dire une adresse) qui pointe vers une zone de la memoire que lui a aloué malloc. zone permanente tant qu'on ne fait pas free()

      quand vous faites
      P= "aaa" ;

      vous faites pointer P vers une AUTRE zone de la memoire . et dans le cas present une zone de la PILE de fonctions. quand le prog sort de wazaa , la zone de "aaa" est perdue et reutilisee pour autre chose. donc plantage garanti.

      ce qu'il faut faire c'est copier "aaa" dans la zone allouee par malloc :

      strcpy (P,"aaa")

      • [^]Re: Petite erreur

        Posté par mansuetus (page perso, ) le 15/09/2004 à 09:40. (lien). Évalué à 0.

        c'est rigolo de voir que ce sujet "tout simple" que j'ai posé de façon un peu ... brutale met pas mal de monde dans l'embarra

        --
        mansuetus @ spontex . org
        • [^]Re: Petite erreur

          Posté par kesako () le 15/09/2004 à 09:59. (lien). Évalué à 1.

          parcequ'on n'enseigne plus le BABA du fonctionnement d'un processeur ( pile, zone memoire, ...)

          on passe tout de suite au java , python , c++ avec des strings

          on ne sait plus comment ca marche effectivement.

          j'ai vu un tres bon programmeur venant de java , qui faisait des copies de maps en c++ pratiquement a chaque ligne ... et les maps etait prevues pour contenir plusieurs milliers d'elements ...

strcpy

Posté par animal_omega () le 15/09/2004 à 09:20. (lien). Évalué à 4.

ha mon avis tu devrais utilise strcopy ou mieux strncopy pour affecter une chaine de caractere

--
#85514
IRC is just multiplayer notepad.
  • [^]Re: strcpy

    Posté par FReEDoM (page perso, ) le 15/09/2004 à 09:31. (lien). Évalué à 2.

    c'est LA bonne réponse de cette page :)

    Les autres aiderons aussi à rencontrer moins de bug mais celle te permettra de résoudre ton problème.

    Dans ta fonction wazza, tu alloue en effet de la mémoire dont tu récupére l'dresse dans ta structure. ça c'est OK, c'est la façon de procéder.
    to_ret->a = malloc (20*sizeof(char));

    Mais appès, tu écrase le pointeur par l'adresse statique d'une variable sur la pile de ta fonction. ça cé mal !
    to_ret->a = "aaa";

    A la place de ça utilise strcpy

    • [^]"Miracle" !

      Posté par mansuetus (page perso, ) le 15/09/2004 à 09:37. (lien). Évalué à 1.

      merci !

      j'avais essayé, mais j'ai du oublier d'allouer la mémoire à l'époque donc segfaults... mais là, mon prog d'origine, celui pour qui je me donne tant de mal peut enfin avancer !

      si j'avais plus de 1 d'XP je plusserais tout le thread ;-)

      --
      mansuetus @ spontex . org
    • [^]Re: strcpy

      Posté par calandoa () le 15/09/2004 à 11:26. (lien). Évalué à 5.

      c'est plutôt UNE des bonnes réponses de cette page!

      Faire un :
      char * titi = "polom polom";
      est tout à fait légal, permis et autorisé.

      Faire un :
      char * titi = (char*) malloc (50*sizeof(char));
      strncpy (titi, "polom polom", 50);
      //éviter le strcpy!!!
      ou un :
      char * titi = strdup ("polom polom"); //presque pareil qu'au dessus
      est encore légal, permis, autorisé.

      Lequel choisir alors? Eh bien ça dépend de ce qu'on va faire de titi...
      Si titi ne va être que lu, on peut utiliser la première méthode. Si titi va être écrit, il FAUT utiliser la seconde méthode (même pour remplacer un seul caractère sans rien rajouter à la fin).

      Et en C, une chaîne entre guillemets dans le source n'est pas stocké dans la pile mais dans le segment DATA du fichier objet.

      Et enfin, faire un :
      char * titi = (char*) malloc (50*sizeof(char));
      titi = "polom polom";

      est autorisé mais fortement déconseillé. Ça ne plantera pas, mais il y aura une fuite mémoire car la valeur renvoyée par le malloc est définitivement perdue avant qu'un free() soit fait. C'est pas bien, mais bon, 99% des programmes ont des fuites mémoire et elles se comptent plus en Ko qu'en dizaines d'octets... Enfin ce n'est pas parce que la majorité des programmeurs sont des sagouins que c'est une excuse pour en être un :-)

      • [^]Re: strcpy

        Posté par kesako () le 15/09/2004 à 12:29. (lien). Évalué à 1.

        > Et en C, une chaîne entre guillemets dans le source n'est pas stocké dans la pile mais dans le segment DATA du fichier objet.

        je n'ai jamais pu me faire a cette idee .

        autant je ne vois pas de pb si c'est dans le main() :
        main () {
        char * titi = "polom polom";

        }

        autant j'ai du mal a avaler que l'ecriture suivante soit ok :

        char * f() {

        char * toto = "abcd" ;

        return toto;
        }

        je prefere utiliser des
        const char * const STUFF = "toto";
        char * f() {

        char * toto = STUFF;

        return toto;
        }
        c'est strictement pareil , et generalement plus propre (centralisation des chaines) et ca me perturbe moins ...

    • [^]Re: strcpy

      Posté par Christophe Fergeau () le 16/09/2004 à 12:42. (lien). Évalué à 2.

      Non, la bonne réponse c'aurait été d'utiliser la glib pour tout ça, et d'éviter au maximum les fonctions de la libc et tous les pbs qui peuvent se poser avec si tu fais pas gaffe...

      ma_struct = g_new0 (sizeof (struct MaStruct), 1);
      ma_struct->chaine1 = g_strdup ("cequejeveux");
      voire même
      ma_struct->chaine2 = g_strdup_printf ("valeur: %u\n", un_entier);
      etc, etc

      Ca ressemble beaucoup aux fonctions de la libc, sauf que c'est portable (ok, strdup doit être portable aussi ;), mais surtout, les fonctions sont beaucoup plus robustes à mon avis... (genre elles renvoient toujours des chaînes terminées par des \0, la plupart du temps on te renvoie une copie, ..)

vive IRC

Posté par doublehp (page perso, ) le 15/09/2004 à 11:43. (lien). Évalué à 1.

heureux posesseur d une vraie connection internet ... va sur irc : irc.freenode.net, chan #c ... et tu aura ta reponse en moins de 1 min.

PS : ne paste pas ton code sur un chan, met le en ligne sur un server web.

--
www.doublehp.org
le site qui sera toujours en construction ...

Un bon bouquin pour le C

Posté par Toufou (page perso, ) le 15/09/2004 à 12:11. (lien). Évalué à 0.

Juste pour te préciser que pour 30¤ tu peux avoir toutes ces infos (et plein d'autres) très clairement expliquées en achetant le bouquin de Kernighan et Ritchie : Le Langage C.
Je tiens a préciser que ce commentaire n'est pas un RTFM de plus, c'est juste un retour d'expérience : je n'ai rien compris au C jusqu'à ce que je lise ce bouquin et depuis, je m'aperçois que beaucoup de programmeurs C professionnels ou non devraient le lire avant de coder des âneries :) Bref, pour 30¤ et allez, un mois de lecture / pratique, tu n'auras plus de soucis avec le langage lui même (le C c'est vraiment très simple comme langage)

  • [^]Re: Un bon bouquin pour le C

    Posté par mansuetus (page perso, ) le 15/09/2004 à 22:21. (lien). Évalué à 0.

    je note la référence pour un usage futur : on a toujours besoin de BONS ouvrages ;-)

    --
    mansuetus @ spontex . org

ddd

Posté par fellix () le 15/09/2004 à 19:57. (lien). Évalué à 1.

Pour voir un peu ce qui se passe avec les structures (il me semble que c'est ta préoccupation initiale), utilise donc un debugger visuel.

DDD (http://www.gnu.org/software/ddd/(...)) par exemple peut tracer pas à pas l'exécution de ton programme, préalablement compilé avec l'option -g de gcc, tout en visualisant sur un graphe le contenu de tes variables (screenshot : http://www.gnu.org/software/ddd/all.jpg(...) ; oui, je sais, c'est du C++...).

Je pense que cette représentation devrait t'aider à comprendre et à maîtriser les structures.

tip : pour savoir (grosso modo) si un pointeur pointe dans le segment de données ou dans la pile avec son adresse :
0x08XXXXXX : données
0xbffXXXXXX : pile
ça peut aider parfois.... (e.g. pour persuader support linux que sss->a ne pointe pas sur la pile ;-) )
(http://www.wlug.org.nz/MemoryMap(...))

  • [^]Re: ddd

    Posté par mansuetus (page perso, ) le 15/09/2004 à 22:18. (lien). Évalué à 0.

    aucune idée de ce pourquoi tu t'es fait moinsser, mais je suivrai ton conseil malgré tout : je m'aperçois que je malloc plus que je free, et d'après ce que tu sembles expliquer ddd peut le voir...

    il me sera au moins utile pour cela.

    Merci donc pour ta remarque, et je ne te plusse pas parce que je n'ai pas le droit :/

    --
    mansuetus @ spontex . org
  • [^]Re: ddd

    Posté par fred point (page perso, ) le 15/09/2004 à 23:00. (lien). Évalué à 1.

    oui en effet j'ma trompé et j'en suis désolé

    dummy () {
    char toto[10]; // sur la pile
    char * titi = "blabla"; // dans DATA
    }

    Mais l'idée qui était importante c'est que :
    a = malloc(...);
    a = "blabla";

    Le malloc est complètement inutile...

    Support linux
    (FReEDoM qui se tape un délire de bénévolat actuellement)

Revenir en haut de page || Retourner aux forums || Retourner au forum Programmation.c