OVH Cloud OVH Cloud

detecter si onbjet est en pile ou dans le tas

6 réponses
Avatar
JBB
J'aimerais savoir si il est possible simplement de détecter si un objet
est alloué dans la pile (ou global) ou si il a été alloué dynamiquement.

exemple de code simplifié:

void f(Maclasse * pMonObjet)
{
//traitements
....

//supprimer l'objet si il est alloué dynamiquement
if ( /* ??? */ )
{
delete pMonObjet;
}
}

main
{
Maclasse objet1;
Maclasse * pobjet2 = new Maclasse ;

f(&objet1);
f(pobjet2);

}


Même si c'est possible, j'imagine qu'on va me dire que c'est une tres
mauvaise idée non?

6 réponses

Avatar
news
JBB wrote:
J'aimerais savoir si il est possible simplement de détecter si un objet
est alloué dans la pile (ou global) ou si il a été alloué dynamiquement.

exemple de code simplifié:

void f(Maclasse * pMonObjet)
{
//traitements
....

//supprimer l'objet si il est alloué dynamiquement
if ( /* ??? */ )
{
delete pMonObjet;
}
}

main
{
Maclasse objet1;
Maclasse * pobjet2 = new Maclasse ;

f(&objet1);
f(pobjet2);

}


Même si c'est possible, j'imagine qu'on va me dire que c'est une tres
mauvaise idée non?



Pourquoi ne pas utiliser un garbage collector plutot?
Ca fera les choses "mieux", je pense. Voir
http://www.hpl.hp.com/personal/Hans_Boehm/gc/ par exemple.

Avatar
Arnaud Meurgues
JBB wrote:

J'aimerais savoir si il est possible simplement de détecter si un objet
est alloué dans la pile (ou global) ou si il a été alloué dynamiquement.


Il me semble me souvenir qu'il y a un article de Effective C++ (ou More
Effective C++) précisément sur ce sujet. Quelqu'un l'aurait-il sous la
main pour vérifier ?

Il me semble aussi que sa conclusion est que ce n'était pas possible.

Arnaud

Avatar
Stan
"Arnaud Meurgues" a écrit dans le
message de news:42e4e342$0$5043$
| JBB wrote:
|
| > J'aimerais savoir si il est possible simplement de détecter si un objet
| > est alloué dans la pile (ou global) ou si il a été alloué
dynamiquement.
|
| Il me semble me souvenir qu'il y a un article de Effective C++ (ou More
| Effective C++) précisément sur ce sujet. Quelqu'un l'aurait-il sous la
| main pour vérifier ?
|
| Il me semble aussi que sa conclusion est que ce n'était pas possible.
|
| Arnaud


C'est peut être possible dans la mesure où on peut appeler new
avec une adresse mémoire.
Mais l'idée initiale me semble plus que douteuse.

--

Stan .
Avatar
kanze
Arnaud Meurgues wrote:
JBB wrote:

J'aimerais savoir si il est possible simplement de détecter
si un objet est alloué dans la pile (ou global) ou si il a
été alloué dynamiquement.


Il me semble me souvenir qu'il y a un article de Effective C++
(ou More Effective C++) précisément sur ce sujet. Quelqu'un
l'aurait-il sous la main pour vérifier ?

Il me semble aussi que sa conclusion est que ce n'était pas possible.


Ce n'est certainement pas possible de façon portable. En
revanche, je sais très bien faire la distinction entre des
objets statiques, autos et dynamiques sous Solaris sur Sparc ;
ça m'est même servi une fois (dans une assertion, où il fallait
que l'objet soit statique).

En ce qui concerne l'idée de s'en servir pour décider si on fait
delete ou non... il faut y ajouter le problème des objets dans
un tableau.

Curieusement, j'ai un problème à peu près pareil à l'instant.
J'ai un type avec une structure interne assez complexe, des
arborescences, etc. Évidemment, la structure se fait à partir
des éléments alloués dynamiquement. Mais un certain nombre
d'instances sont prédéfinies et constantes. Pour elles, je
génère la structure off line, statiquement. (Les éléments de la
structure ont été soigneusement conçus de façon à être des PODs,
de façon à permettre l'initialisation avec les {...}.) Dans mon
cas, les initialisations à partir des statiques utilise un
constructeur spécial (privé) ; j'ai donc la possibilité de
positionner un drappeau dans le constructeur, pour me dire si je
dois appeler delete ou non. Mais en fait, j'ai installé le gc de
Boehm hier soir -- c'est une solution encore beaucoup plus
élégante.

(Reste le problème que si je donne des constructeurs à
l'utilisateur -- chose qu'il faut ici, la classe même a toujours
une initialisation dynamique. Or que ce que je cherche, c'est
bien de me libérer des problèmes de l'ordre d'initialisation.)

--
James Kanze GABI Software
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
kanze
Stan (remove 1,2,3) wrote:
"Arnaud Meurgues" a
écrit dans le message de
news:42e4e342$0$5043$

| JBB wrote:

| > J'aimerais savoir si il est possible simplement de
| > détecter si un objet est alloué dans la pile (ou global)
| > ou si il a été alloué dynamiquement.

| Il me semble me souvenir qu'il y a un article de Effective
| C++ (ou More Effective C++) précisément sur ce
| sujet. Quelqu'un l'aurait-il sous la main pour vérifier ?

| Il me semble aussi que sa conclusion est que ce n'était pas
| possible.

C'est peut être possible dans la mesure où on peut appeler new
avec une adresse mémoire. Mais l'idée initiale me semble plus
que douteuse.


La solution « classique », c'était de surcharger l'operator new
pour la classe en question :

static bool dynamic = false ;

void*
MaClasse::operator new( size_t n )
{
try {
dynamic = true ;
return ::operator new( n ) ;
} catch ( .. ) {
dynamic = false ;
throw ;
}
}

et dans le constructeur :

MaClasse::MaClasse()
: myIsDynamic( dynamic )
{
dynamic = false ;
}

Évidemment, ça pose un petit problème avec les threads (mais si
on mettait « dynamic » en mémoire locale à chaque thread ?). Et
il ne s'adresse pas non plus à la question d'un tableau de
MaClasse.

Sous Unix (et seulement sous Unix, je crois, et peut-être même
pas sous tous les Unix), l'éditeur de liens créer un symbole
« end » à la fin des données (qu'il met au début de la
mémoire). Si l'adresse de ton objet est inférieur à l'adresse
d'end, l'objet a une durée de vie statique. Sur des Unix où la
pile hardware croît vers le bas, souvent (c'est le cas sous
Solaris sur Sparc et de Linux sur PC), l'éditeur de liens met la
pile vers le haut. Dans ce cas, si l'adresse de ton objet est
supérieur à l'adresse d'un objet local déclaré sur la pile,
c'est que ton objet est sur la pile. Et si l'objet n'est ni
statique, ni sur la pile, c'est qu'il a été alloué par new. À
moins qu'on a mmappé un fichier, et triché avec des pointeurs,
ou d'autres choses du genre.

Donc, ce n'est pas portable, et ce n'est pas robuste. Mais il
peut marcher dans certains cas limites. (Comme j'ai dit, je ne
m'en suis servi que dans des assert. La correction du programme
n'en est jamais dépendu.)

--
James Kanze GABI Software
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
Stan
a écrit dans le message de news:

C'est peut être possible dans la mesure où on peut appeler new
avec une adresse mémoire. Mais l'idée initiale me semble plus
que douteuse.

La solution « classique », c'était de surcharger l'operator new
pour la classe en question :

static bool dynamic = false ;

void*
MaClasse::operator new( size_t n )
{
try {
dynamic = true ;
return ::operator new( n ) ;
} catch ( .. ) {
dynamic = false ;
throw ;
}
}

et dans le constructeur :

MaClasse::MaClasse()
: myIsDynamic( dynamic )
{
dynamic = false ;
}



Après reflexion, la solution à laquelle j'avais pensé
n'est même pas réalisable :

void* mem= reinterpret_cast<void*>( 0x800000); // adresse de la zone
d'allocation

UneClasse* pt = new( mem ) UneClasse;

Le test consistait à comparer l'addresse de l'instanse pour
savoir si elle avait été créée depuis mem ou pas.

--
-Stan