kanze wrote:Sylvain wrote:Michel Decima wrote on 28/09/2006 21:50:Sylvain wrote:faute de pouvoir ne rien lui fournir, on peut lui
fournir rien en le faisant passer pour qlq chose ...
A* first = null;
A a(*first);
Est ce que *first a un comportement defini si first vaut
NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas
la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique'
du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur
(warning au maximum).
Si vous connaissez un compilateur pour lequel cette ligne ne
passe pas, je serais intéressé d'en connaitre le nom.
kanze wrote:
Sylvain wrote:
Michel Decima wrote on 28/09/2006 21:50:
Sylvain wrote:
faute de pouvoir ne rien lui fournir, on peut lui
fournir rien en le faisant passer pour qlq chose ...
A* first = null;
A a(*first);
Est ce que *first a un comportement defini si first vaut
NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas
la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique'
du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur
(warning au maximum).
Si vous connaissez un compilateur pour lequel cette ligne ne
passe pas, je serais intéressé d'en connaitre le nom.
kanze wrote:Sylvain wrote:Michel Decima wrote on 28/09/2006 21:50:Sylvain wrote:faute de pouvoir ne rien lui fournir, on peut lui
fournir rien en le faisant passer pour qlq chose ...
A* first = null;
A a(*first);
Est ce que *first a un comportement defini si first vaut
NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas
la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique'
du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur
(warning au maximum).
Si vous connaissez un compilateur pour lequel cette ligne ne
passe pas, je serais intéressé d'en connaitre le nom.
Michel Decima wrote on 17/10/2006 00:14:
Je connais au moins un compilateur qui refuse ce code. Si vous pensez
que cela n'est pas conforme, je vous laisse l'honneur du bug report.
Comeau C/C++ 4.3.8 (Aug 19 2006 13:36:48) for ONLINE_EVALUATION_Alpha1
un bug report sur une version d'éval ?!??
c'est payé combien par report ?
Michel Decima wrote on 17/10/2006 00:14:
Je connais au moins un compilateur qui refuse ce code. Si vous pensez
que cela n'est pas conforme, je vous laisse l'honneur du bug report.
Comeau C/C++ 4.3.8 (Aug 19 2006 13:36:48) for ONLINE_EVALUATION_Alpha1
un bug report sur une version d'éval ?!??
c'est payé combien par report ?
Michel Decima wrote on 17/10/2006 00:14:
Je connais au moins un compilateur qui refuse ce code. Si vous pensez
que cela n'est pas conforme, je vous laisse l'honneur du bug report.
Comeau C/C++ 4.3.8 (Aug 19 2006 13:36:48) for ONLINE_EVALUATION_Alpha1
un bug report sur une version d'éval ?!??
c'est payé combien par report ?
Michel Decima wrote:*first n'implique pas forcément un déréférencement 'mécaniq ue' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une variable
temporaire. => "x" est évalué. A partir de là, l'initialisation
possède un objet avec une adresse. Par conséquent, retour au premier
cas.
De plus, un comportement non défini devrait (mais ce n'est pas
toujours le cas...) générer de la part du compilateur
uniquement un warning.
Michel Decima wrote:
*first n'implique pas forcément un déréférencement 'mécaniq ue' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une variable
temporaire. => "x" est évalué. A partir de là, l'initialisation
possède un objet avec une adresse. Par conséquent, retour au premier
cas.
De plus, un comportement non défini devrait (mais ce n'est pas
toujours le cas...) générer de la part du compilateur
uniquement un warning.
Michel Decima wrote:*first n'implique pas forcément un déréférencement 'mécaniq ue' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une variable
temporaire. => "x" est évalué. A partir de là, l'initialisation
possède un objet avec une adresse. Par conséquent, retour au premier
cas.
De plus, un comportement non défini devrait (mais ce n'est pas
toujours le cas...) générer de la part du compilateur
uniquement un warning.
Michel Decima wrote:L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une varia ble
temporaire. => "x" est évalué. A partir de là, l'initialisati on
possède un objet avec une adresse. Par conséquent, retour au prem ier
cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le
resultat de la compilation ?
*(int*) 0
Cette expression spécifie un objet de type int dont l'adresse
est 0. (<=> définition d'une lvalue)
Définition d'une lvalue dans la norme c++ :
lvalue : une expression qui réfère à un objet.
A un autre endroit, la norme utilise également cette définition
(équivalente dans la pratique):
lvalue : un objet dont on peut prendre l'adresse.
[Précision à ce sujet : la norme c++ indique clairement qu'une
lvalue n'est pas forcément un objet qui peut se placer à
gauche de l'opérateur d'assignement, tel qu'on l'entend
souvent.]
L'expression est donc une lvalue.
Nous sommes dans le 1er cas.
Le compilateur devrait laisser passer cette ligne (il ne
devrait pas tenter un déréférencement).
Michel Decima wrote:
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une varia ble
temporaire. => "x" est évalué. A partir de là, l'initialisati on
possède un objet avec une adresse. Par conséquent, retour au prem ier
cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le
resultat de la compilation ?
*(int*) 0
Cette expression spécifie un objet de type int dont l'adresse
est 0. (<=> définition d'une lvalue)
Définition d'une lvalue dans la norme c++ :
lvalue : une expression qui réfère à un objet.
A un autre endroit, la norme utilise également cette définition
(équivalente dans la pratique):
lvalue : un objet dont on peut prendre l'adresse.
[Précision à ce sujet : la norme c++ indique clairement qu'une
lvalue n'est pas forcément un objet qui peut se placer à
gauche de l'opérateur d'assignement, tel qu'on l'entend
souvent.]
L'expression est donc une lvalue.
Nous sommes dans le 1er cas.
Le compilateur devrait laisser passer cette ligne (il ne
devrait pas tenter un déréférencement).
Michel Decima wrote:L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une varia ble
temporaire. => "x" est évalué. A partir de là, l'initialisati on
possède un objet avec une adresse. Par conséquent, retour au prem ier
cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le
resultat de la compilation ?
*(int*) 0
Cette expression spécifie un objet de type int dont l'adresse
est 0. (<=> définition d'une lvalue)
Définition d'une lvalue dans la norme c++ :
lvalue : une expression qui réfère à un objet.
A un autre endroit, la norme utilise également cette définition
(équivalente dans la pratique):
lvalue : un objet dont on peut prendre l'adresse.
[Précision à ce sujet : la norme c++ indique clairement qu'une
lvalue n'est pas forcément un objet qui peut se placer à
gauche de l'opérateur d'assignement, tel qu'on l'entend
souvent.]
L'expression est donc une lvalue.
Nous sommes dans le 1er cas.
Le compilateur devrait laisser passer cette ligne (il ne
devrait pas tenter un déréférencement).
Falk Tannhäuser wrote:schrieb:
Notamment :the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'objet
référencé).
Je réitère donc ma demande : si vous connaissez un compilateur
qui produit un déréférencement "mécanique" lors de l'opération
d'initialisation de la référence, merci de m'en donner le nom,
je n'en ai encore rencontré aucun, même en se basant une
version debug du code.
Falk Tannhäuser wrote:
dieu.tout.puissant@gmail.com schrieb:
Notamment :
the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'objet
référencé).
Je réitère donc ma demande : si vous connaissez un compilateur
qui produit un déréférencement "mécanique" lors de l'opération
d'initialisation de la référence, merci de m'en donner le nom,
je n'en ai encore rencontré aucun, même en se basant une
version debug du code.
Falk Tannhäuser wrote:schrieb:
Notamment :the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'objet
référencé).
Je réitère donc ma demande : si vous connaissez un compilateur
qui produit un déréférencement "mécanique" lors de l'opération
d'initialisation de la référence, merci de m'en donner le nom,
je n'en ai encore rencontré aucun, même en se basant une
version debug du code.
kanze wrote:Sylvain wrote:Michel Decima wrote on 28/09/2006 21:50:Sylvain wrote:faute de pouvoir ne rien lui fournir, on peut lui fournir rien en
le
faisant passer pour qlq chose ...
A* first = null;
A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas
la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum). Si vous connaissez un compilateur pour lequel cette ligne ne
passe pas, je serais intéressé d'en connaitre le nom.
kanze wrote:
Sylvain wrote:
Michel Decima wrote on 28/09/2006 21:50:
Sylvain wrote:
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en
le
faisant passer pour qlq chose ...
A* first = null;
A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas
la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum). Si vous connaissez un compilateur pour lequel cette ligne ne
passe pas, je serais intéressé d'en connaitre le nom.
kanze wrote:Sylvain wrote:Michel Decima wrote on 28/09/2006 21:50:Sylvain wrote:faute de pouvoir ne rien lui fournir, on peut lui fournir rien en
le
faisant passer pour qlq chose ...
A* first = null;
A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas
la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum). Si vous connaissez un compilateur pour lequel cette ligne ne
passe pas, je serais intéressé d'en connaitre le nom.
wrote:Michel Decima wrote:L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'es t pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une var iable
temporaire. => "x" est évalué. A partir de là, l'initialisa tion
possède un objet avec une adresse. Par conséquent, retour au pr emier
cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le
resultat de la compilation ?
*(int*) 0
Cette expression spécifie un objet de type int dont l'adresse
est 0. (<=> définition d'une lvalue)
Non. C'est un cas particulier. Ici, l'expression « 0 » est une
expression constante de type entier qui s'évalue à 0. C'est donc
un constante de pointeur nul. Le convertir en pointeur, donc,
donne un pointeur nul, qui par définition ne désigne aucun objet
(« distinguishable from every other value of pointer to object
or pointer to function type »). S'il peut exister un objet à
l'adresse 0 (rarement le cas sur des machines modernes), le
résultat de ton expression ne peut pas être l'adresse 0. (Et il
a bel et bien existé des machines où l'expression (int*)0
donnait un pointeur dont tous les bits n'étaient pas à zéro, les
anciens Prime, par exemple.)
Et par définition, donc, (int*)0 ne désigne pas un objet, et
*(int*)0 n'est pas légal (parce que l'opérateur * convertit un
pointeur en lvalue, et un lvalue doit désigner un objet).
dieu.tout.puissant@gmail.com wrote:
Michel Decima wrote:
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'es t pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une var iable
temporaire. => "x" est évalué. A partir de là, l'initialisa tion
possède un objet avec une adresse. Par conséquent, retour au pr emier
cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le
resultat de la compilation ?
*(int*) 0
Cette expression spécifie un objet de type int dont l'adresse
est 0. (<=> définition d'une lvalue)
Non. C'est un cas particulier. Ici, l'expression « 0 » est une
expression constante de type entier qui s'évalue à 0. C'est donc
un constante de pointeur nul. Le convertir en pointeur, donc,
donne un pointeur nul, qui par définition ne désigne aucun objet
(« distinguishable from every other value of pointer to object
or pointer to function type »). S'il peut exister un objet à
l'adresse 0 (rarement le cas sur des machines modernes), le
résultat de ton expression ne peut pas être l'adresse 0. (Et il
a bel et bien existé des machines où l'expression (int*)0
donnait un pointeur dont tous les bits n'étaient pas à zéro, les
anciens Prime, par exemple.)
Et par définition, donc, (int*)0 ne désigne pas un objet, et
*(int*)0 n'est pas légal (parce que l'opérateur * convertit un
pointeur en lvalue, et un lvalue doit désigner un objet).
wrote:Michel Decima wrote:L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'es t pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une var iable
temporaire. => "x" est évalué. A partir de là, l'initialisa tion
possède un objet avec une adresse. Par conséquent, retour au pr emier
cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le
resultat de la compilation ?
*(int*) 0
Cette expression spécifie un objet de type int dont l'adresse
est 0. (<=> définition d'une lvalue)
Non. C'est un cas particulier. Ici, l'expression « 0 » est une
expression constante de type entier qui s'évalue à 0. C'est donc
un constante de pointeur nul. Le convertir en pointeur, donc,
donne un pointeur nul, qui par définition ne désigne aucun objet
(« distinguishable from every other value of pointer to object
or pointer to function type »). S'il peut exister un objet à
l'adresse 0 (rarement le cas sur des machines modernes), le
résultat de ton expression ne peut pas être l'adresse 0. (Et il
a bel et bien existé des machines où l'expression (int*)0
donnait un pointeur dont tous les bits n'étaient pas à zéro, les
anciens Prime, par exemple.)
Et par définition, donc, (int*)0 ne désigne pas un objet, et
*(int*)0 n'est pas légal (parce que l'opérateur * convertit un
pointeur en lvalue, et un lvalue doit désigner un objet).
wrote:Falk Tannhäuser wrote:schrieb:
[...]Notamment :the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'obj et
référencé).
Ça veut dire quoi, déréférencement « mécanique » ?
Et moi, je peux te
dire que je me suis déjà servi d'un compilateur où il ne
marchait pas -- le compilateur généré systèmatiquement des
tests pour un pointeur null chaque fois qu'on se servait de
l'opérateur * unaire.
dieu.tout.puissant@gmail.com wrote:
Falk Tannhäuser wrote:
dieu.tout.puissant@gmail.com schrieb:
[...]
Notamment :
the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'obj et
référencé).
Ça veut dire quoi, déréférencement « mécanique » ?
Et moi, je peux te
dire que je me suis déjà servi d'un compilateur où il ne
marchait pas -- le compilateur généré systèmatiquement des
tests pour un pointeur null chaque fois qu'on se servait de
l'opérateur * unaire.
wrote:Falk Tannhäuser wrote:schrieb:
[...]Notamment :the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'obj et
référencé).
Ça veut dire quoi, déréférencement « mécanique » ?
Et moi, je peux te
dire que je me suis déjà servi d'un compilateur où il ne
marchait pas -- le compilateur généré systèmatiquement des
tests pour un pointeur null chaque fois qu'on se servait de
l'opérateur * unaire.
kanze wrote:wrote:Falk Tannhäuser wrote:schrieb:
[...]Notamment :the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'o bjet
référencé).
Ça veut dire quoi, déréférencement « mécanique » ?
Mon explication du terme déréférencement "mécanique" laisse à
désirer. Pour l'améliorer, je vais donc lister le code asm,
non optimisé, généré par mon compilateur, vc++ 8 (pas besoin
de bien connaitre l'assembleur pour comprendre).
int *p = 0;
mov dword ptr [p],0
int &r = *p;
mov eax,dword ptr [p]
mov dword ptr [r],eax
int v = *p;
mov eax,dword ptr [p]
mov ecx,dword ptr [eax] ; déréférencement mécanique
mov dword ptr [v],ecx
Voilà la différence entre l'initialisation d'une référence et
d'un objet. L'opération d'initialisation de référence
n'implique pas de déréférencement mécanique.
La norme ne tient pas compte de la réalité du terrain (on
dirait un discours politique).
int *p = 0;
int &r = *p;
Il n'y a aucun intérêt à déréférencer (mécaniquement) p. A
quoi servirait la valeur de l'objet pointé par p?
S'il y a déréférencement dans ce cas-là, il y aura crash à
l'exécution. Je n'ai encore rencontré aucun compilateur qui
sacrifie la rapidité du code (génère une instruction de plus)
dans le but de provoquer un crash.
Et moi, je peux te dire que je me suis déjà servi d'un
compilateur où il ne marchait pas -- le compilateur généré
systèmatiquement des tests pour un pointeur null chaque fois
qu'on se servait de l'opérateur * unaire.
Si tu peux te souvenir du nom de ce compilateur, j'aimerais
vraiment étudier la manière dont il génère ce genre de test.
En effet, pour que ce test soit valide pour n'importe quelles
applications, le pointeur doit se trouver sur la pile. Sinon
(le pointeur est lui-même un objet pointé se trouvant sur le
tas), l'ensemble de cette opération(test + déréférencement)
est non atomique (pas de test&set pour les déréférencements)
et le compilateur doit normalement poser un lock, sauf si le
compilateur ne génère que du code monothreadé.
kanze wrote:
dieu.tout.puissant@gmail.com wrote:
Falk Tannhäuser wrote:
dieu.tout.puissant@gmail.com schrieb:
[...]
Notamment :
the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'o bjet
référencé).
Ça veut dire quoi, déréférencement « mécanique » ?
Mon explication du terme déréférencement "mécanique" laisse à
désirer. Pour l'améliorer, je vais donc lister le code asm,
non optimisé, généré par mon compilateur, vc++ 8 (pas besoin
de bien connaitre l'assembleur pour comprendre).
int *p = 0;
mov dword ptr [p],0
int &r = *p;
mov eax,dword ptr [p]
mov dword ptr [r],eax
int v = *p;
mov eax,dword ptr [p]
mov ecx,dword ptr [eax] ; déréférencement mécanique
mov dword ptr [v],ecx
Voilà la différence entre l'initialisation d'une référence et
d'un objet. L'opération d'initialisation de référence
n'implique pas de déréférencement mécanique.
La norme ne tient pas compte de la réalité du terrain (on
dirait un discours politique).
int *p = 0;
int &r = *p;
Il n'y a aucun intérêt à déréférencer (mécaniquement) p. A
quoi servirait la valeur de l'objet pointé par p?
S'il y a déréférencement dans ce cas-là, il y aura crash à
l'exécution. Je n'ai encore rencontré aucun compilateur qui
sacrifie la rapidité du code (génère une instruction de plus)
dans le but de provoquer un crash.
Et moi, je peux te dire que je me suis déjà servi d'un
compilateur où il ne marchait pas -- le compilateur généré
systèmatiquement des tests pour un pointeur null chaque fois
qu'on se servait de l'opérateur * unaire.
Si tu peux te souvenir du nom de ce compilateur, j'aimerais
vraiment étudier la manière dont il génère ce genre de test.
En effet, pour que ce test soit valide pour n'importe quelles
applications, le pointeur doit se trouver sur la pile. Sinon
(le pointeur est lui-même un objet pointé se trouvant sur le
tas), l'ensemble de cette opération(test + déréférencement)
est non atomique (pas de test&set pour les déréférencements)
et le compilateur doit normalement poser un lock, sauf si le
compilateur ne génère que du code monothreadé.
kanze wrote:wrote:Falk Tannhäuser wrote:schrieb:
[...]Notamment :the only way to create such a reference would be to bind it
to the "object" obtained by dereferencing a null pointer
Ce déréférencement "syntaxique" n'implique pas de
déréférencement "mécanique" (c'est-à-dire l'accès à l'o bjet
référencé).
Ça veut dire quoi, déréférencement « mécanique » ?
Mon explication du terme déréférencement "mécanique" laisse à
désirer. Pour l'améliorer, je vais donc lister le code asm,
non optimisé, généré par mon compilateur, vc++ 8 (pas besoin
de bien connaitre l'assembleur pour comprendre).
int *p = 0;
mov dword ptr [p],0
int &r = *p;
mov eax,dword ptr [p]
mov dword ptr [r],eax
int v = *p;
mov eax,dword ptr [p]
mov ecx,dword ptr [eax] ; déréférencement mécanique
mov dword ptr [v],ecx
Voilà la différence entre l'initialisation d'une référence et
d'un objet. L'opération d'initialisation de référence
n'implique pas de déréférencement mécanique.
La norme ne tient pas compte de la réalité du terrain (on
dirait un discours politique).
int *p = 0;
int &r = *p;
Il n'y a aucun intérêt à déréférencer (mécaniquement) p. A
quoi servirait la valeur de l'objet pointé par p?
S'il y a déréférencement dans ce cas-là, il y aura crash à
l'exécution. Je n'ai encore rencontré aucun compilateur qui
sacrifie la rapidité du code (génère une instruction de plus)
dans le but de provoquer un crash.
Et moi, je peux te dire que je me suis déjà servi d'un
compilateur où il ne marchait pas -- le compilateur généré
systèmatiquement des tests pour un pointeur null chaque fois
qu'on se servait de l'opérateur * unaire.
Si tu peux te souvenir du nom de ce compilateur, j'aimerais
vraiment étudier la manière dont il génère ce genre de test.
En effet, pour que ce test soit valide pour n'importe quelles
applications, le pointeur doit se trouver sur la pile. Sinon
(le pointeur est lui-même un objet pointé se trouvant sur le
tas), l'ensemble de cette opération(test + déréférencement)
est non atomique (pas de test&set pour les déréférencements)
et le compilateur doit normalement poser un lock, sauf si le
compilateur ne génère que du code monothreadé.
wrote:
S'il y a déréférencement dans ce cas-là, il y aura crash à
l'exécution. Je n'ai encore rencontré aucun compilateur qui
sacrifie la rapidité du code (génère une instruction de plus)
dans le but de provoquer un crash.
Il te manque de l'expérience, alors, parce que la plupart des
compilateurs aujourd'hui ont des options pour insérer du code de
vérification dans certains cas. Et ce n'est pas une nouveauté.
Et moi, je peux te dire que je me suis déjà servi d'un
compilateur où il ne marchait pas -- le compilateur généré
systèmatiquement des tests pour un pointeur null chaque fois
qu'on se servait de l'opérateur * unaire.
Si tu peux te souvenir du nom de ce compilateur, j'aimerais
vraiment étudier la manière dont il génère ce genre de test.
Le compilateur, c'était le compilateur de Green Hills. Je ne
sais pas ce qui lui en est devenu aujourd'hui.
Il y a un autre compilateur dont on me dit qu'il faisait pareil.
J'ai un trou de mémoire en ce qui concerne son nom à l'instant,
mais à l'époque, il était assez connu pour tester tout. (Il se
vendait comme compilateur de « contrôle » ; son but n'était
pas de compiler l'exécutable qu'on livrait, mais de compiler
avec un maximum de vérifications, de façon à ce qu'on détecte un
maximum d'erreurs.)En effet, pour que ce test soit valide pour n'importe quelles
applications, le pointeur doit se trouver sur la pile. Sinon
(le pointeur est lui-même un objet pointé se trouvant sur le
tas), l'ensemble de cette opération(test + déréférencement)
est non atomique (pas de test&set pour les déréférencements)
et le compilateur doit normalement poser un lock, sauf si le
compilateur ne génère que du code monothreadé.
Tu te moques de nous ou quoi ? Si un autre thread peut modifier
le pointeur, l'utilisateur a déjà un lock. Sinon, il a un
comportement indéfini, qui risque réelement de lui causer des
ennuis. (N'oublie pas que la lecture d'un pointeur n'est pas
forcément atomique. Au moins, pas sur un Intel.)
dieu.tout.puissant@gmail.com wrote:
S'il y a déréférencement dans ce cas-là, il y aura crash à
l'exécution. Je n'ai encore rencontré aucun compilateur qui
sacrifie la rapidité du code (génère une instruction de plus)
dans le but de provoquer un crash.
Il te manque de l'expérience, alors, parce que la plupart des
compilateurs aujourd'hui ont des options pour insérer du code de
vérification dans certains cas. Et ce n'est pas une nouveauté.
Et moi, je peux te dire que je me suis déjà servi d'un
compilateur où il ne marchait pas -- le compilateur généré
systèmatiquement des tests pour un pointeur null chaque fois
qu'on se servait de l'opérateur * unaire.
Si tu peux te souvenir du nom de ce compilateur, j'aimerais
vraiment étudier la manière dont il génère ce genre de test.
Le compilateur, c'était le compilateur de Green Hills. Je ne
sais pas ce qui lui en est devenu aujourd'hui.
Il y a un autre compilateur dont on me dit qu'il faisait pareil.
J'ai un trou de mémoire en ce qui concerne son nom à l'instant,
mais à l'époque, il était assez connu pour tester tout. (Il se
vendait comme compilateur de « contrôle » ; son but n'était
pas de compiler l'exécutable qu'on livrait, mais de compiler
avec un maximum de vérifications, de façon à ce qu'on détecte un
maximum d'erreurs.)
En effet, pour que ce test soit valide pour n'importe quelles
applications, le pointeur doit se trouver sur la pile. Sinon
(le pointeur est lui-même un objet pointé se trouvant sur le
tas), l'ensemble de cette opération(test + déréférencement)
est non atomique (pas de test&set pour les déréférencements)
et le compilateur doit normalement poser un lock, sauf si le
compilateur ne génère que du code monothreadé.
Tu te moques de nous ou quoi ? Si un autre thread peut modifier
le pointeur, l'utilisateur a déjà un lock. Sinon, il a un
comportement indéfini, qui risque réelement de lui causer des
ennuis. (N'oublie pas que la lecture d'un pointeur n'est pas
forcément atomique. Au moins, pas sur un Intel.)
wrote:
S'il y a déréférencement dans ce cas-là, il y aura crash à
l'exécution. Je n'ai encore rencontré aucun compilateur qui
sacrifie la rapidité du code (génère une instruction de plus)
dans le but de provoquer un crash.
Il te manque de l'expérience, alors, parce que la plupart des
compilateurs aujourd'hui ont des options pour insérer du code de
vérification dans certains cas. Et ce n'est pas une nouveauté.
Et moi, je peux te dire que je me suis déjà servi d'un
compilateur où il ne marchait pas -- le compilateur généré
systèmatiquement des tests pour un pointeur null chaque fois
qu'on se servait de l'opérateur * unaire.
Si tu peux te souvenir du nom de ce compilateur, j'aimerais
vraiment étudier la manière dont il génère ce genre de test.
Le compilateur, c'était le compilateur de Green Hills. Je ne
sais pas ce qui lui en est devenu aujourd'hui.
Il y a un autre compilateur dont on me dit qu'il faisait pareil.
J'ai un trou de mémoire en ce qui concerne son nom à l'instant,
mais à l'époque, il était assez connu pour tester tout. (Il se
vendait comme compilateur de « contrôle » ; son but n'était
pas de compiler l'exécutable qu'on livrait, mais de compiler
avec un maximum de vérifications, de façon à ce qu'on détecte un
maximum d'erreurs.)En effet, pour que ce test soit valide pour n'importe quelles
applications, le pointeur doit se trouver sur la pile. Sinon
(le pointeur est lui-même un objet pointé se trouvant sur le
tas), l'ensemble de cette opération(test + déréférencement)
est non atomique (pas de test&set pour les déréférencements)
et le compilateur doit normalement poser un lock, sauf si le
compilateur ne génère que du code monothreadé.
Tu te moques de nous ou quoi ? Si un autre thread peut modifier
le pointeur, l'utilisateur a déjà un lock. Sinon, il a un
comportement indéfini, qui risque réelement de lui causer des
ennuis. (N'oublie pas que la lecture d'un pointeur n'est pas
forcément atomique. Au moins, pas sur un Intel.)