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

Probleme de virtual (le retour)

4 réponses
Avatar
Doms
Bonjour,

j'etais venu ici bas discuter d'un probleme de virtualisation de fonction
qui ne marche pas complètement. En gros, de temps à autre, lorsque j'execute
mon code (compilé avec g++ sous linux/Mac OS, ca fonctionne sous
Visual), lors de l'execution d'une fonction membre virtuelle, j'ai une adresse
invalide.

J'ai un peu progresser sur le detail du probleme. L'exposé des faits.
J'ai une librarie à 3 couches (en fait 3 libraries dont la premiere est
utilisée par la seconde, la troisieme utilisant les 2 précédente).
J'ai besoin d'initialiser des objets *avant le main* de l'utilisateur
de la librarie. Et pour cela, j'ai fait un mecanisme avec des objets
d'initialisation (1 pour chaque couche) qui me permet de garantir
que j'initialise bien la couche 1 avant la 2, puis la 3. J'ai donc
une classe d'initialisation pour chaque couche qui fait appel à celle
d'en dessous. Ce mecanisme fonctionne bien (pour l'ordre d'appel).
L'idée la derriere est de ne pas instumenter le main (puisque penible
a faire de maniere portbale surtout avec les différents types de
projet visual studio) et parceque cela peut poser plus de probleme
que de solution.

Le problème qui se pose est qu'en fait la derniere couche crée 1 thread
(ca fait partie de son initialisation) et ce thread commence a utiliser
des classes dont l'une possède des fonctions membres virtuelles
(pas abstraites cette fois-ci). Et en fonction de l'ordonancement du
systeme (en gros pas souvent mais quand meme), ca plante car
l'adresse de la fonction membre n'est pas correcte. constaté avec
gdb.

Avez-vous une idée de comment rendre cela plus propre. Comment
peut-on etre certain de l'initialisation de la table vituelle d'une classe
puisque le fait d'avoir ete dans son constructeur, d'avoir deja appelé
2 fonctions membres n'est pas critique pour cela ?

En vous remerciant de toute lumiere sur le sujet.

Doms.

4 réponses

Avatar
Michael DOUBEZ
[snip]
Le problème qui se pose est qu'en fait la derniere couche crée 1 thread
(ca fait partie de son initialisation) et ce thread commence a utiliser
des classes dont l'une possède des fonctions membres virtuelles
(pas abstraites cette fois-ci). Et en fonction de l'ordonancement du
systeme (en gros pas souvent mais quand meme), ca plante car
l'adresse de la fonction membre n'est pas correcte. constaté avec
gdb.



Est ce qu'il s'agit d'un "Pure Virtual Function Called" ?
Je te conseil l'article:
http://www.artima.com/cppsource/pure_virtual.html

Ce qqi m'est arrivé avec une class de thread c'est que le design fait
que c'est une des fonction membre virtuel de la class qui est executé
dans le thread. Si dans une class dérivé, tu t'amuse à démarrer le
thread dans le constructeur, tu peux arriver à utiliser un objet non
terminé.

Michael

Avatar
Doms
Bonjour,

Est ce qu'il s'agit d'un "Pure Virtual Function Called" ?
Je te conseil l'article:
http://www.artima.com/cppsource/pure_virtual.html

Ce qqi m'est arrivé avec une class de thread c'est que le design fait que c'est une des fonction membre virtuel de la class qui
est executé dans le thread. Si dans une class dérivé, tu t'amuse à démarrer le thread dans le constructeur, tu peux arriver à
utiliser un objet non terminé.


C'est presque ca (j'avais ca et j'avais resolu). Maintenant, le probleme
c'est que je lance un thread qui cree un objet dont la table virtuelle n'est
pas initialisée.

Doms.

Avatar
James Kanze
Doms wrote:
j'etais venu ici bas discuter d'un probleme de
virtualisation de fonction qui ne marche pas complètement.
En gros, de temps à autre, lorsque j'execute mon code
(compilé avec g++ sous linux/Mac OS, ca fonctionne sous
Visual), lors de l'execution d'une fonction membre
virtuelle, j'ai une adresse invalide.

J'ai un peu progresser sur le detail du probleme. L'exposé
des faits. J'ai une librarie à 3 couches (en fait 3
libraries dont la premiere est utilisée par la seconde, la
troisieme utilisant les 2 précédente). J'ai besoin
d'initialiser des objets *avant le main* de l'utilisateur
de la librarie. Et pour cela, j'ai fait un mecanisme avec
des objets d'initialisation (1 pour chaque couche) qui me
permet de garantir que j'initialise bien la couche 1 avant
la 2, puis la 3. J'ai donc une classe d'initialisation
pour chaque couche qui fait appel à celle d'en dessous. Ce
mecanisme fonctionne bien (pour l'ordre d'appel). L'idée
la derriere est de ne pas instumenter le main (puisque
penible a faire de maniere portbale surtout avec les
différents types de projet visual studio) et parceque cela
peut poser plus de probleme que de solution.

Le problème qui se pose est qu'en fait la derniere couche
crée 1 thread (ca fait partie de son initialisation) et ce
thread commence a utiliser des classes dont l'une possède
des fonctions membres virtuelles (pas abstraites cette
fois-ci). Et en fonction de l'ordonancement du systeme (en
gros pas souvent mais quand meme), ca plante car l'adresse
de la fonction membre n'est pas correcte. constaté avec
gdb.


Ce ne m'est pas trop clair. Un petit bout de code aurait aidé.
Ça ne m'est pas du tout clair comment tu invoques
l'initialisation des couches plus basses. Si c'est avec des
objets statiques, l'ordre d'initialisation entre les objets
statiques dans de différentes unités de compilation n'est pas
défini. Alors, si la couche supérieur est initialisée avant les
couches plus basses, le thread que tu y lances risque d'utiliser
les objets dans les couches plus basse avant qu'ils soient
initialisés.

Avez-vous une idée de comment rendre cela plus propre.
Comment peut-on etre certain de l'initialisation de la
table vituelle d'une classe puisque le fait d'avoir ete
dans son constructeur, d'avoir deja appelé 2 fonctions
membres n'est pas critique pour cela ?


La table virtuelle est bonne une fois que tu sors du
constructeur. Toujours. Alors, ou bien tu n'as pas fini
l'exécution du constructeur, ou bien tu as un problème ailleurs
qui modifie le vptr dans l'instance de la classe.

--
James Kanze (GABI Software, from CAI) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Doms
Bonjour,

Ce ne m'est pas trop clair. Un petit bout de code aurait aidé.


Le code est en ligne (OMiSCID version C++). Difficile
d'extraire juste ce bout de code la...

Ça ne m'est pas du tout clair comment tu invoques
l'initialisation des couches plus basses. Si c'est avec des
objets statiques, l'ordre d'initialisation entre les objets
statiques dans de différentes unités de compilation n'est pas
défini. Alors, si la couche supérieur est initialisée avant les
couches plus basses, le thread que tu y lances risque d'utiliser
les objets dans les couches plus basse avant qu'ils soient
initialisés.


L'ordre d'initialisation est géré. Si on mets les traces,
on voit bien que les fonctions d'initialisations sont bien
appelées dans le bon ordre. Le probleme doit venir
de l'initialisation faites automatiquement par le compilo...

La table virtuelle est bonne une fois que tu sors du
constructeur. Toujours. Alors, ou bien tu n'as pas fini
l'exécution du constructeur, ou bien tu as un problème ailleurs
qui modifie le vptr dans l'instance de la classe.


Je suis déjà sorti du constructeur et j'ai deja appelé
des fonctions membres non virtuelles. Bref, c'est la
le probleme. Je vais essayer de faire l'init ailleurs
en utilisant des compteurs d'instances mais ca me plaisais
moyen comme methode.

Doms.
--
James Kanze (GABI Software, from CAI) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34