Retourner aux forums || Retourner au forum Programmation.c
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 !)
> Lire le message (22 commentaires, moyenne: 1,8).
malloc
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 !-
[^]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 !
-
Petite erreur
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
-
[^]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
ha mon avis tu devrais utilise strcopy ou mieux strncopy pour affecter une chaine de caractere
-
[^]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 ;-)
-
[^]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
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.
Un bon bouquin pour le C
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 ;-)
ddd
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 :/
-
[^]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



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.