OVH Cloud OVH Cloud

Obtenir l'adresse d'un élément de vecteur

36 réponses
Avatar
Marc
Bonjour,
j'utilise des vecteurs du type

vector<ClassA> mon_vecteur;

Dans une fonction, j'ai besoin de passer comme paramètre l'adresse d'un
élément du vecteur (c'est comme ça...), c'est à dire un paramètre du type
ClassA*.
Quand je tente
&mon_vecteur.at(i)
ça plante.
Quelqu'un sait pourquoi ?
En fait j'ai besoin de stocker quelque part les adresses des éléments du
vecteur.
Merci
Marc

6 réponses

1 2 3 4
Avatar
kanze
"Michel Michaud" wrote in message
news:<A1dBb.108$...
Dans news:,
Mais je n'apprécie pas que Michel puisse penser que je pourrais être
assez amateur pour écrire quelque chose du genre &v[nbElem]
simplement parce que je savais que mon implémentation (aujourd'hui)
n'effectuait pas de vérification.


Alors tu apprécieras de savoir que ce n'est pas ce que j'ai dit.

J'ai dit que s'il n'y a pas d'alternative (et je parlais en général,
pas seulement de [] vs at), tu vas choisir ce qui fonctionne plutôt
que ce qui serait mieux mais ne fonctionne pas. C'est ce que j'ai
compris de ton choix <iostream.h> vs <iostream> entre autres. Tu dois
t'arranger pour que tes programmes fonctionnent parfaitement, avec les
limites et les possibilités des outils mis à ta disposition. Je fais
erreur ?


En gros, non. C'est évidemment plus nuancé, du fait que je porte parfois
plusieurs châpeaux, mais en gros, mes clients me paient pour quelque
chose qui marche et qu'on peut maintenir. Avec les outils qu'on a -- je
n'ai pas droit de me cacher derrière les faiblesses du compilateur.

Et qu'il ne suffit pas que les programmes marchent ; il faut qu'ils
soient démonstrablement corrects, et que les collègues puissent les
comprendre et y intervenir le jour où je ne suis plus là.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
Michel Michaud
Dans news:,

De point de vue de l'exception safety, c'est beaucoup moins
dangereux. Parce qu'avec les bibliothèques dont je me sers
professionnellement actuellement, [nbElem] provoque un échec d'une
assertion. Pas de problème d'exception safety, mais ce n'est pas
une solution pratique pour que l'application marche non plus.


Est-ce que faire un assert est vraiment permis (dans un mode
production, en particulier) ? Il me semble que la norme donne
des garanties sur un certain nombre de choses, par exemple sur
l'existence des éléments alloués. Même si je ne vois comment
faire autrement), il me semble que ceci ne devrait pas donner
d'erreur (d'aucune sorte), en ce sens qu'il s'agit d'un code
vraiment sans danger :

vector<int> v;
v.reserve(100);
int* premier= &v[0];
int* dernier= &v[99];

Les pointeurs premier et dernier pourraient être utiles pour
une raison ou une autre. On ne voudrait probablement jamais
les déréférencer. De toute façon, *premier et *dernier devrait
être sans danger, même si on ne remplit pas le vecteur. Le
processeur ne peut pas détecter des adresses illégales, car
elles sont dans une zone de mémoire vraiment allouée.

[...]
Dans mes propres classes de tableau, il y a actuellement trois
possibilités prévues :

[] échec de l'assertion en cas d'erreur
at() exception en cas d'erreur, et
unsafeAt() pas de vérification, pour le cas où le profiler dit
qu'il faut.


Je sais bien que nous n'avons pas la même définition de « assert »,
mais si ton []/assert détecte quelque chose, c'est qu'il y a une
erreur dans ton programme non ? Ne serait-ce pas mieux que ton []
lève une exception (genre du type EncoreUnBogue), que tu pourrais
capter afin de ne pas simplement laisser le programme s'arrêter ?

En fait, pour mes élèves, en mode debug, [] fait comme at. Je
trouve que c'est raisonnable. Vraiment si on a le moindre doute,
je crois qu'il faut utiliser at... et capter les exceptions !

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/

Avatar
kanze
"Michel Michaud" wrote in message
news:<jjwBb.2$...
Dans news:,

De point de vue de l'exception safety, c'est beaucoup moins
dangereux. Parce qu'avec les bibliothèques dont je me sers
professionnellement actuellement, [nbElem] provoque un échec d'une
assertion. Pas de problème d'exception safety, mais ce n'est pas une
solution pratique pour que l'application marche non plus.


Est-ce que faire un assert est vraiment permis (dans un mode
production, en particulier) ?


J'avoue que dans la mode production, j'ai une tendance à remplacer
l'assert avec ma propre assert, afin de donner un message d'erreur avec
des choses comme le numéro de téléphone du support technique. Mais c'est
un détail.

En tout cas, il faut arrêter le programme. Continuer n'est pas une option.

Il me semble que la norme donne des garanties sur un certain nombre de
choses, par exemple sur l'existence des éléments alloués. Même si je
ne vois comment faire autrement), il me semble que ceci ne devrait pas
donner d'erreur (d'aucune sorte), en ce sens qu'il s'agit d'un code
vraiment sans danger :

vector<int> v;
v.reserve(100);
int* premier= &v[0];
int* dernier= &v[99];


La norme est claire. C'est un comportement indéfini.

Les pointeurs premier et dernier pourraient être utiles pour une
raison ou une autre. On ne voudrait probablement jamais les
déréférencer. De toute façon, *premier et *dernier devrait être sans
danger, même si on ne remplit pas le vecteur. Le processeur ne peut
pas détecter des adresses illégales, car elles sont dans une zone de
mémoire vraiment allouée.


Est-ce que tu es en train de suggérer un changement de la norme, ou
quelque chose d'autre ? La norme dit que c'est un comportement indéfini.
Dans la pratique, le code ne marche pas avec la STLPort ni avec les
dernières versions de Dinkumware (d'après ce que j'ai entendu dire, en
tout cas). Le permettre rendra la vérification des bornes quasi
impossible ; c'est ça que tu veux.

[...]
Dans mes propres classes de tableau, il y a actuellement trois
possibilités prévues :

[] échec de l'assertion en cas d'erreur
at() exception en cas d'erreur, et
unsafeAt() pas de vérification, pour le cas où le profiler dit
qu'il faut.


Je sais bien que nous n'avons pas la même définition de « assert »,
mais si ton []/assert détecte quelque chose, c'est qu'il y a une
erreur dans ton programme non ?


Tout à fait. Il y a une erreur dans le programme, on ne sait plus si les
invariantes les plus fondamentales tiennent, et la seule action qu'on
peut oser, c'est d'arrêter la plus vite possible.

Ne serait-ce pas mieux que ton [] lève une exception (genre du type
EncoreUnBogue), que tu pourrais capter afin de ne pas simplement
laisser le programme s'arrêter ?


Non, parce qu'une exception execute du code. Appeler les destructeurs
sur des objets où l'invariante n'est plus respecter peut faire des
dégats qu'il vaut mieux éviter.

Dans la passer (avec mes propres classes), je me servais de mon propre
assert, et non celui de la norme. Ça permettait d'inscrire des actions
qu'il fallait tenter coût que coût en cas d'erreur. Dans la pratique, je
n'en ai pas rencontré ; c'était toujours plus dangereux de les tenter
sans savoir l'état du programme que de s'en passer.

En fait, pour mes élèves, en mode debug, [] fait comme at. Je trouve
que c'est raisonnable. Vraiment si on a le moindre doute, je crois
qu'il faut utiliser at... et capter les exceptions !


Il y a toute une question là. Ma propre préférence va aux vérifications
explicites extern au tableau, mais je conçois qu'on puisse vouloir
exploiter les vérifications du tableau pour la détection des erreurs
(dans les données d'entées, etc.), surtout quand on a des raisons à
croire que de telles erreurs soient exceptionnelles.

Mais en général, dans mon code, je n'ai pas le doute. Donc, assert.
Parce que si je n'ai pas le doute, et que ça s'est passé quand même,
c'est que je me suis trompé, et que je ne sais pas ce que fait le
programme. Et dans ce cas-là, il faut mieux qu'il fasse le moins
possible par la suite, pour éviter de faire plus de dégat.

(Il y a des exceptions à cette règle -- dans un programme de démo, par
exemple, où on veut éviter un crash visible à tout prix.)

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
Loïc Joly
wrote:


Non, parce qu'une exception execute du code. Appeler les destructeurs
sur des objets où l'invariante n'est plus respecter peut faire des
dégats qu'il vaut mieux éviter.


Je suis dubitatif à ce sujet.
J'ai l'intuition qu'il y a des cas d'utilisation où il vaut mieux tant
bin que mal essayer de se rattraper aux branches pour exécuter du code
de sortie de programme que d'arrêter brutalement.
Même si dans certains cas c'est peine perdu, il y aura quand même
quelques cas où ce code s'exécute correctement, et rien que pour ces
cas, ça peut en valoir le coup.

--
Loïc

Avatar
Jean-Marc Bourguet
Loïc Joly writes:

wrote:

Non, parce qu'une exception execute du code. Appeler les destructeurs
sur des objets où l'invariante n'est plus respecter peut faire des
dégats qu'il vaut mieux éviter.


Je suis dubitatif à ce sujet.
J'ai l'intuition qu'il y a des cas d'utilisation où il vaut mieux tant bin
que mal essayer de se rattraper aux branches pour exécuter du code de
sortie de programme que d'arrêter brutalement.


Je peux imaginer des cas ou ca vaut la peine d'avoir, en cas de
detection d'incoherences, du code prevu pour qui fait plus que
d'afficher un message et de sortir. Mais ce doit etre du code
specifique et simplement jeter une exception et esperer que le
traitement normal de l'exception permettra d'etre mieux me semble
illusoire.

Dans le genre de chose que je ne ferais pas, il y a l'effacement ou
l'ecrasement de donnees utilisateurs. On peut a la rigueur envisage
de sauver l'etat actuel mais dans un nouveau fichier (et d'experience
-- j'ai travaille sur un programme qui le faisait -- ca ne sert a
rien).


Même si dans certains cas c'est peine perdu, il y aura quand même
quelques cas où ce code s'exécute correctement, et rien que pour ces
cas, ça peut en valoir le coup.


Est-ce que ca vaut le coup par rapport au cas ou le code fait des
choses stupides? Avec un programme bien concu, on perd rarement
beaucoup plus que du temps et encore essentiellement du temps machine.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
kanze
Loïc Joly wrote in message
news:<br7tn9$5ks$...
wrote:

Non, parce qu'une exception execute du code. Appeler les
destructeurs sur des objets où l'invariante n'est plus respecter
peut faire des dégats qu'il vaut mieux éviter.


Je suis dubitatif à ce sujet.


Sur quelles bases ? (De l'expérience avec des applications robustes ?
Des études particulières ? Des articles que tu as lus ?)

J'ai l'intuition qu'il y a des cas d'utilisation où il vaut mieux tant
bin que mal essayer de se rattraper aux branches pour exécuter du code
de sortie de programme que d'arrêter brutalement.


Il y a des cas, comme des programmes de démo, où masquer l'erreur à tout
prix est la bonne solution. C'est certain. Dans la plupart des
applications, en revanche, les cas où ça se produisent doivent être
tellement rares (parce que tu as bien tester le code, n'est-ce pas), et
la risque que ça comporte tellement grande, qu'il vaut mieux ne pas
essayer.

Enfin, c'est mon expérience. Chaque fois qu'on a essayé à continuer, ça
a fait plus de mal que de bien. Je suis conforté dans cette expérience
de constater que d'autres experts me la confirment, David Abrahams, par
exemple.

Même si dans certains cas c'est peine perdu, il y aura quand même
quelques cas où ce code s'exécute correctement, et rien que pour ces
cas, ça peut en valoir le coup.


Le problème, ce n'est pas que c'est peine perdu. Le problème, c'est
qu'on risque de faire des dégats -- d'écrire des choses sur disque, par
exemple, qui sont fausses, ou de corrompre autrement le système.

Il faut dire que quand on en arrive là :
- On a déjà « prouvé » dans les revues du code que le cas ne peut pas
se produire.
- On fait subir aux programme des tests exhaustifs et le cas ne s'est
pas produit.
Alors, si le cas se produit lors de l'utilisation, c'est qu'il y a
quelque chose qui cloche dans la procédure ci-dessus. Et s'il y a
quelque chose qui cloche dans cette procédure, c'est qu'on ne sait pas
réelement ce que risque de faire le code par la suite.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


1 2 3 4