Je dirais que oui (en plus, pas de warning) mais quand même j'ai un doute : bien
que les chaînes littérales soient en mémoire statique, le compilateur va-t-il
retourner la même adresse à chaque appel ? Bon en fait quand on dit que les
chaînes sont en mémoire statique, je trouve que c'est un peu vague. La Norme,
elle, dit :
A character string literal has static storage duration and type
"array of char ,"
mais dans un programme on écrit
int toto=42, titi;
titi=toto + strlen("zozo");
le compilateur place-t-il en mémoire statique la chaîne "zozo" parce que je vois
pas l'intérêt de le faire ? Par contre si on écrit
char *s="zozo";
je vois l'intérêt puisque l'adresse est utilisée par une variable
D'ailleurs, dans le premier exemple, la variable ok a-t-elle toujours la même
valeur ? Je crois que oui mais j'ai un petit doute.
Donc d'après toi le code précédent ne va pas afficher 2 fois la même chose et une opération magique va changer la valeur de la variable locale p au moment du free ?
En fait, ce n'est même pas obligé. D'après la norme, la valeur du pointeur devient indéterminé quand l'objet qu'il pointe n'existe plus.
§ 6.2.4.2 [...] The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime.
Et tu connais une plateforme où, dans mon exemple, la variable locale p est modifiée entre les 2 print ?
Pas en C (question de perfs), mais j'ai déjà vu une implémentation de GC qui récupérait les pointeurs tels que p, ainsi que tous les alias, et les modifiaient au sein même de l'implémentation de l'équivalent du free(). L'objectif était surtout d'éviter les doubles free(), mais l'effet obtenu était celui auquel tu fais allusion, la valeur du pointeur apparaissait modifiée.
J'imagine bien une appli avec pleins de malloc où les adresses sont stockées dans des structures, et un free fait que de façon immédiate quelque chose change tous les pointeurs des structures pour rendre "indéterminé" ces mêmes pointeurs.
J'imagine bien une implémentation où les alloc() sont implémentés pour aller le plus vite possible, et où c'est free() qui fait le plus gros du boulot. Avec les manières de programmer de certains, c'est peut-être même rentable en termes de performances :-).
Donc d'après toi le code précédent ne va pas afficher 2 fois la même
chose et une opération magique va changer la valeur de la variable
locale p au moment du free ?
En fait, ce n'est même pas obligé. D'après la norme, la valeur du
pointeur devient indéterminé quand l'objet qu'il pointe n'existe plus.
§ 6.2.4.2 [...] The value of a pointer becomes indeterminate when the
object it points to reaches the end of its lifetime.
Et tu connais une plateforme où, dans mon exemple, la variable locale p est
modifiée entre les 2 print ?
Pas en C (question de perfs), mais j'ai déjà vu une implémentation de GC
qui récupérait les pointeurs tels que p, ainsi que tous les alias, et
les modifiaient au sein même de l'implémentation de l'équivalent du
free(). L'objectif était surtout d'éviter les doubles free(), mais
l'effet obtenu était celui auquel tu fais allusion, la valeur du
pointeur apparaissait modifiée.
J'imagine bien une appli avec pleins de malloc où les adresses sont stockées
dans des structures, et un free fait que de façon immédiate quelque chose
change tous les pointeurs des structures pour rendre "indéterminé" ces mêmes
pointeurs.
J'imagine bien une implémentation où les alloc() sont implémentés pour
aller le plus vite possible, et où c'est free() qui fait le plus gros du
boulot. Avec les manières de programmer de certains, c'est peut-être
même rentable en termes de performances :-).
Donc d'après toi le code précédent ne va pas afficher 2 fois la même chose et une opération magique va changer la valeur de la variable locale p au moment du free ?
En fait, ce n'est même pas obligé. D'après la norme, la valeur du pointeur devient indéterminé quand l'objet qu'il pointe n'existe plus.
§ 6.2.4.2 [...] The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime.
Et tu connais une plateforme où, dans mon exemple, la variable locale p est modifiée entre les 2 print ?
Pas en C (question de perfs), mais j'ai déjà vu une implémentation de GC qui récupérait les pointeurs tels que p, ainsi que tous les alias, et les modifiaient au sein même de l'implémentation de l'équivalent du free(). L'objectif était surtout d'éviter les doubles free(), mais l'effet obtenu était celui auquel tu fais allusion, la valeur du pointeur apparaissait modifiée.
J'imagine bien une appli avec pleins de malloc où les adresses sont stockées dans des structures, et un free fait que de façon immédiate quelque chose change tous les pointeurs des structures pour rendre "indéterminé" ces mêmes pointeurs.
J'imagine bien une implémentation où les alloc() sont implémentés pour aller le plus vite possible, et où c'est free() qui fait le plus gros du boulot. Avec les manières de programmer de certains, c'est peut-être même rentable en termes de performances :-).
Antoine
Xavier Roche
Pierre Maurette a écrit :
void* bidon = &p; uintptr_t* u = (uintptr_t)bidon;
plutôt uintptr_t* u = (uintptr_t*)bidon;
[utiliser *u] A quel moment ça coince ?
Ah, une illustration de mon message précédent: c'est une violation de l'"aliasing" C (ie. deux adresses identiques ayant des types fortement différents ne peuvent co-exister) ; *u est donc totalement indéfini.
Pierre Maurette a écrit :
void* bidon = &p;
uintptr_t* u = (uintptr_t)bidon;
plutôt
uintptr_t* u = (uintptr_t*)bidon;
[utiliser *u]
A quel moment ça coince ?
Ah, une illustration de mon message précédent: c'est une violation de
l'"aliasing" C (ie. deux adresses identiques ayant des types fortement
différents ne peuvent co-exister) ; *u est donc totalement indéfini.
void* bidon = &p; uintptr_t* u = (uintptr_t)bidon;
plutôt uintptr_t* u = (uintptr_t*)bidon;
[utiliser *u] A quel moment ça coince ?
Ah, une illustration de mon message précédent: c'est une violation de l'"aliasing" C (ie. deux adresses identiques ayant des types fortement différents ne peuvent co-exister) ; *u est donc totalement indéfini.
Pierre Maurette
Xavier Roche, le 14/07/2009 a écrit :
Pierre Maurette a écrit :
void* bidon = &p; uintptr_t* u = (uintptr_t)bidon;
plutôt uintptr_t* u = (uintptr_t*)bidon;
Bien entendu. Merci.
[utiliser *u] A quel moment ça coince ?
Ah, une illustration de mon message précédent: c'est une violation de l'"aliasing" C (ie. deux adresses identiques ayant des types fortement différents ne peuvent co-exister) ; *u est donc totalement indéfini.
Je me trompe sans doute, mais je ne suis pas convaincu. J'ai le sentiment qu'on est un peu dans le "tout est possible et son contraire". &p existe et est une constante, il y a quelques règles qu'il me faudrait retrouver précisément qui parlent de convertibilité d'un pointeur en void* et vice-versa, d'un rapport entre void* et un type entier, et je ne vois pas de cas où ça planterait en cas de pointeur non valide alors qu'on sait que ça marche en cas de pointeur valide.
-- Pierre Maurette
Xavier Roche, le 14/07/2009 a écrit :
Pierre Maurette a écrit :
void* bidon = &p;
uintptr_t* u = (uintptr_t)bidon;
plutôt
uintptr_t* u = (uintptr_t*)bidon;
Bien entendu. Merci.
[utiliser *u]
A quel moment ça coince ?
Ah, une illustration de mon message précédent: c'est une violation de
l'"aliasing" C (ie. deux adresses identiques ayant des types fortement
différents ne peuvent co-exister) ; *u est donc totalement indéfini.
Je me trompe sans doute, mais je ne suis pas convaincu. J'ai le
sentiment qu'on est un peu dans le "tout est possible et son
contraire". &p existe et est une constante, il y a quelques règles
qu'il me faudrait retrouver précisément qui parlent de convertibilité
d'un pointeur en void* et vice-versa, d'un rapport entre void* et un
type entier, et je ne vois pas de cas où ça planterait en cas de
pointeur non valide alors qu'on sait que ça marche en cas de pointeur
valide.
void* bidon = &p; uintptr_t* u = (uintptr_t)bidon;
plutôt uintptr_t* u = (uintptr_t*)bidon;
Bien entendu. Merci.
[utiliser *u] A quel moment ça coince ?
Ah, une illustration de mon message précédent: c'est une violation de l'"aliasing" C (ie. deux adresses identiques ayant des types fortement différents ne peuvent co-exister) ; *u est donc totalement indéfini.
Je me trompe sans doute, mais je ne suis pas convaincu. J'ai le sentiment qu'on est un peu dans le "tout est possible et son contraire". &p existe et est une constante, il y a quelques règles qu'il me faudrait retrouver précisément qui parlent de convertibilité d'un pointeur en void* et vice-versa, d'un rapport entre void* et un type entier, et je ne vois pas de cas où ça planterait en cas de pointeur non valide alors qu'on sait que ça marche en cas de pointeur valide.
-- Pierre Maurette
Xavier Roche
Pierre Maurette a écrit :
&p existe et est une constante, il y a quelques règles qu'il me faudrait retrouver précisément qui parlent de convertibilité d'un pointeur en void* et vice-versa
Cela n'empêche pas les problèmes d'aliasing.
Pierre Maurette a écrit :
&p existe et est une constante, il y a quelques règles qu'il me faudrait
retrouver précisément qui parlent de convertibilité d'un pointeur en
void* et vice-versa
&p existe et est une constante, il y a quelques règles qu'il me faudrait retrouver précisément qui parlent de convertibilité d'un pointeur en void* et vice-versa