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 !)
# malloc
Posté par Me Nut (site web personnel) . Évalué à 1.
struct structure *test = malloc( 60 * sizeof( char ));
au lieu de
struct structure *test;
[^] # On progresse... mais c'est pas encore gagné...
Posté par mansuetus (site web personnel) . Évalué à 1.
---------------------------
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 (site web personnel) . Évalué à 2.
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 );
}
[^] # Re: On progresse... mais c'est pas encore gagné...
Posté par FReEDoM (site web personnel) . Évalué à 2.
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 (site web personnel) . Évalué à 0.
en fait, ça marche, je me suis gourré en modifiant...
merci !
# Petite erreur
Posté par alberthier (site web personnel) . Évalué à 2.
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 (site web personnel) . Évalué à 2.
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 . Évalué à 5.
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 (site web personnel) . Évalué à 0.
[^] # Re: Petite erreur
Posté par kesako . Évalué à 1.
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 . Évalué à 4.
[^] # Re: strcpy
Posté par FReEDoM (site web personnel) . Évalué à 2.
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 (site web personnel) . Évalué à 1.
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 . Évalué à 5.
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 . Évalué à 1.
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 . Évalué à 2.
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 (site web personnel) . Évalué à 1.
PS : ne paste pas ton code sur un chan, met le en ligne sur un server web.
# Un bon bouquin pour le C
Posté par Toufou (site web personnel) . Évalué à 0.
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 (site web personnel) . Évalué à 0.
# ddd
Posté par fellix . Évalué à 1.
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 (site web personnel) . Évalué à 0.
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 . Évalué à 1.
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)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.