Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Petite question simple avec un pointeur

37 réponses
Avatar
Florent Clairambault
Voila, j'ai un :
char *fich_s = "sortie.txt";

Je voudrais pouvoir en changer la valeur, j'ai esayé :
strcpy(fich_s, "sortie-auto.txt");

Ca ne marche pas... Que dois - je faire ???

Florent

10 réponses

1 2 3 4
Avatar
Charlie Gordon
"Florent 'flure' C." wrote in message
news:

Mais alors, que deviennent les 9 octets précédemment alloués ?


Ils sont toujours alloués (durée de vie égale à celle du programme)


C'est donc bien ce que je craignais : une fuite de mémoire !!!


Pas du tout !
Ce n'est pas une fuite de mémoire. Il n'y a pas eu d'allocation.
Les deux chaines font partie des données statiques de ton programme.
Quand tu écris

p = "toto";

Tu changes la valeur du pointeur p pour y mettre l'adresse du tableau
statique de caractères "toto"

Si plus loin dans le code tu écris:

p = "tototiti";

Tu changes de nouveau le pointeur p pour y mettre cette fois-ci l'adresse de
"tototiti";

Si tu fais cela dans une boucle:

char *p;
int i;
for (i = 0; i < 1000; i++) {
p = "toto";
p = "tutu";
}

Aucune mémoire n'est allouée, aucune chaine n'est copiée, aucune fuite n'a
lieu.
p oscille entre l'adresse de l'un et l'autre tableau.

Pour comprendre le C, il *faut* comprendre la notion de pointeur, c'est
fondamental, et il semble que ce soit non trivial.

Mon pote Joel prétend même que c'est un don :
http://www.joelonsoftware.com/articles/fog0000000073.html

Tu peux lire les notes d'Emmanuel :
http://mapage.noos.fr/emdel/notes.htm#pointeurs

Pour ma part, j'ai une image assez percutante : la pince à linge et le gant
de toilette.

le pointeur c'est la pince à linge.
le programme c'est ton sac a dos : dedans il y a un livre d'instructions (la
fonction main), une pince à linge (le pointeur p) et 2 gants de toilette
"toto" et "tutu". le sac est accroché au mur, tout cela est dans le sac
donc rien ne fuit. Tu es *dans* le sac, tu lis le livre d'instructions, tu
saisis avec la pince successivement le gant "toto" et le gant "tutu". Pas
très utile, mais plus hygiénique quand même.

Maintenant si tu écris le code suivant :

p = malloc(1000);

tu achètes au système une (grande) serviette de bain, que tu saisis avec la
pince à linge, mais qui est à l'extérieur du sac ;-)
si tu la laches sans l'avoir saisi avec une autre pince (un autre pointeur),
elle tombe ! et comme tu tu vois pas où elle tombe, et que de toute façon
tu pourrais pas la ramasser, elle est perdue.
Ça c'est une fuite. Si tu en veux une autre il va falloir re-payer. Alors
que tu aurais dû la rendre avec :

free(p);

Note bien que le pointeur p est encore accroché à la serviette que tu as
rendue, mais elle n'est plus à toi. Donc si tu essaye de t'en re-servir,
c'est du vol : si tu n'as pas de chance, c'est la peine capitale, mais il se
peut que le système ne s'en offusque pas, mais sais-tu à quoi à elle a servi
entre temps ? donc il est préférable d'éviter de garder des attaches comme
ça. On peut détacher une pince simplement en faisant:

p = NULL;

Ça revient à dire que la pince ne tient plus rien.
Evidemment, si tu te débarbouilles avec, ça fait mal !

remarque bien qu'avec malloc la serviette n'est même pas propre, il faut la
nettoyer avec memset.
mais memset ne peut rien pour toi après free, parce que la serviette peut
être déchirée, en feu, ou aux mains du voisin qui est ceinture noire de
karaté.

Les puristes diront qu'on n'utilise pas les mêmes pinces pour les gants et
les serviettes, que ce n'est pas le même tissu... ça se défend !

J'ai même entendu dire (mais c'est hors sujet sur ce forum) qu'à Java, on se
débarbouille avec des lingettes et s'essuie avec du Sopalin, on jette le
tout et que toutes ces questions de fuites, c'est du passé ! En fait ils
prennent tout avec des pincettes, les chambres sont tout de suite
dégueulasses, et il faut payer quelqu'un à plein temps pour nettoyer.

Qui a des questions ?

Chqrlie.



Avatar
cedric
Florent 'flure' C. wrote:
Mais alors, que deviennent les 9 octets précédemment alloués ?


Ils sont toujours alloués (durée de vie égale à celle du programme)



C'est donc bien ce que je craignais : une fuite de mémoire !!!


Ahlala, si tu avais commencé par apprendre l'assembleur ! ;-)

Les chaînes constantes employées partout dans ton programmes vont être
allouées statiquement quelque part (si possible en mémoire en lecture
seule). Comme toute donnée initialisée statiquement, elle figure dans
ton fichier exécutable et est recopiée en mémoire ainsi que le code de
ton programme (sous réserve que tout ceci ait un sens sur ton
architecture - soyons prudent...)

Bref, si tu fait toto = "titi" puis toto = "tata" tu as 10 chars pour
ces deux chaînes en mémoire une fois pour toute, et un pointeur (toto)
qui vaut l'adresse de l'une puis l'adresse de l'autre - une fois que tu
le réaffectes, tu perds définitivement l'adresse de la première chaîne,
et oui c'est cruel.

La taille mémoire utilisé par ton programme n'augmente pas quand cette
réaffectation est exécuté, ce n'est donc pas une fuite mémoire.



Avatar
Florent 'flure' C.
Le Wed, 06 Oct 2004 01:29:53 +0200, cedric a écrit :

Florent 'flure' C. wrote:
Mais alors, que deviennent les 9 octets précédemment alloués ?


Ils sont toujours alloués (durée de vie égale à celle du programme)



C'est donc bien ce que je craignais : une fuite de mémoire !!!


Ahlala, si tu avais commencé par apprendre l'assembleur ! ;-)


Le pire, c'est que j'en ai fait beaucoup, y compris professionnellement,
et je n'avais pas fait le lien entre les chaînes statiques en C et celles
en asm. Désolé, honte à moi.

--
Florent "flure" C.
Décrypter l'@ pour répondre
Coders don't die, they just JMP without RET !




Avatar
Antoine Leca
En ,
Florent 'flure' C. va escriure:

Mais alors, que deviennent les 9 octets précédemment alloués ?


Ils sont toujours alloués (durée de vie égale à celle du programme)


C'est donc bien ce que je craignais : une fuite de mémoire !!!


Peut-être, mais tu n'as pas à t'en préoccuper.

Il y a trois types de mémoire en C : les données statiques, qui existent
depuis avant le big bang jusqu'à la fin des temps; les données "auto"
(normalement sur la pile), qui commencent à exister quand tu rentres dans le
cadre englobant et qui disparaissent comme par enchantement quand on sort du
dit cadre (donc ne jamais /return/er un pointeur vers ces données-là); et
les données alloués (dites « sur le tas », /heap/ en anglais), qui
apparaissent quand on le leur demande (malloc, calloc, strdup) et
disparraissent quand on le leur dit poliment (free).

Le problème des fuites de mémoire ne concerne qu'exclusivement la troisième
catégorie, parce que c'est à toi, Programmeur, de contrôler ce qui se passe
(être poli, quoi). Pour les deux catégories, tu n'as pas de réel contrôle
sur ce qui se passe, donc ce n'est pas ton problème.


Rassuré ?


Antoine



Avatar
Florent Clairambault
En fait, un prof d'info m'a dis que c'était :
pour char* fich_s;
fich_s = (char *) malloc(strlen("Nouvelle chaine"));

Voila, j'ai l'étrange impression, que c'est pas encore gagné pour tout le
monde la programmation...

Florent


"Florent Clairambault" a écrit dans le message de
news:cju2os$ci7$
Voila, j'ai un :
char *fich_s = "sortie.txt";

Je voudrais pouvoir en changer la valeur, j'ai esayé :
strcpy(fich_s, "sortie-auto.txt");

Ca ne marche pas... Que dois - je faire ???

Florent




Avatar
Laurent Deniau
Antoine Leca wrote:
En ,
Florent 'flure' C. va escriure:



Mais alors, que deviennent les 9 octets précédemment alloués ?


Ils sont toujours alloués (durée de vie égale à celle du programme)


C'est donc bien ce que je craignais : une fuite de mémoire !!!



Peut-être, mais tu n'as pas à t'en préoccuper.

Il y a trois types de mémoire en C : les données statiques, qui existent
depuis avant le big bang jusqu'à la fin des temps;


oula, j'ai des collegues qui pourraient argumenter sur cette assertion
pendant des lustres, avec a la clef des posts encore plus long que ceux
de James :-)

a+, ld.




Avatar
Charlie Gordon
"Florent Clairambault" wrote in message
news:ck0h52$mtn$
En fait, un prof d'info m'a dis que c'était :
pour char* fich_s;
fich_s = (char *) malloc(strlen("Nouvelle chaine"));

Voila, j'ai l'étrange impression, que c'est pas encore gagné pour tout le
monde la programmation...



Effectivement, il manquera un octet au tableau alloué par malloc pour
contenir le NUL final de la chaine "Nouvelle chaine".
Pour cet usage, utlise:

char *fich_s = strdup("Nouvelle chaine");

Et il faut naturellement veiller à la libérer (free) à bon escient.

Chqrlie.

Avatar
Richard Delorme
En fait, un prof d'info m'a dis que c'était :
pour char* fich_s;
fich_s = (char *) malloc(strlen("Nouvelle chaine"));


C'est plutôt :
fich_s = malloc(strlen("Nouvelle chaine") + 1);

Le cast (char*) est inutile, sauf si tu recherches une compatibilité
C++, ce qui est mal vu par certains ici.
Il faut allouer 1 caractère de plus que la longueur de la chaine pour
stocker le '' terminal.

--
Richard

Avatar
Laurent Deniau
Charlie Gordon wrote:
"Florent Clairambault" wrote in message
news:ck0h52$mtn$

En fait, un prof d'info m'a dis que c'était :
pour char* fich_s;
fich_s = (char *) malloc(strlen("Nouvelle chaine"));

Voila, j'ai l'étrange impression, que c'est pas encore gagné pour tout le
monde la programmation...




Effectivement, il manquera un octet au tableau alloué par malloc pour
contenir le NUL final de la chaine "Nouvelle chaine".
Pour cet usage, utlise:

char *fich_s = strdup("Nouvelle chaine");


strdup n'est pas standard.

a+, ld.


Avatar
Richard Delorme

Pour cet usage, utlise:

char *fich_s = strdup("Nouvelle chaine");


Attention, strdup ne fait pas partie de la bibliothèque C standard, mais
est une extension (XSI).

--
Richard

1 2 3 4