OVH Cloud OVH Cloud

Comment delete connait-il la taille du block à désallouer ?

17 réponses
Avatar
nico
Bonjour,

Comment "delete" connait-il la taille du block à désallouer ?
(question dans le cadre d'une surcharge de l'opérateur delete)


void operator delete(void * obj)
{
//ici sizeof(obj) renvoie une taille incorrecte
// dans le cadre d'héritage...
}

Merci.

--
nico

10 réponses

1 2
Avatar
Jean-Marc Bourguet
nico writes:

Comment "delete" connait-il la taille du block à désallouer ?


Il doit le deduire de l'adresse passee.

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
nico
nico wrote:

Bonjour,

Comment "delete" connait-il la taille du block à désallouer ?
(question dans le cadre d'une surcharge de l'opérateur delete)


void operator delete(void * obj)
{
//ici sizeof(obj) renvoie une taille incorrecte
// dans le cadre d'héritage...
}

Merci.



oups je pensais sizeof(*obj) mais ca ne marche pas evidemment

--
nico

Avatar
nico
Jean-Marc Bourguet wrote:

nico writes:

Comment "delete" connait-il la taille du block à désallouer ?


Il doit le deduire de l'adresse passee.

A+



Comment ?

--
nico


Avatar
nico
nico wrote:

Bonjour,

Comment "delete" connait-il la taille du block à désallouer ?
(question dans le cadre d'une surcharge de l'opérateur delete)


void operator delete(void * obj)
{
//ici sizeof(obj) renvoie une taille incorrecte
// dans le cadre d'héritage...
}

Merci.



une technique pas élégante mais qui marche :

#define delete(x) __delete(x)
template<class T> void __delete(T* obj)
{
//sizeof(T) fonctionne correctemet
}



--
nico

Avatar
kanze
nico wrote:

Comment "delete" connait-il la taille du block à désallouer ?
(question dans le cadre d'une surcharge de l'opérateur delete)

void operator delete(void * obj)
{
//ici sizeof(obj) renvoie une taille incorrecte
// dans le cadre d'héritage...


Même sans l'héritage:-). La taille d'un void* ne change pas
beaucoup.

}


C'est le problème de l'implementation ; si elle a besoin de la
taille, il faut qu'elle puisse le retrouver à partir de
l'adresse.

Typiquement, l'implémentation va utiliser un en-tête au bloc,
avec toutes les informations dont elle a besoin. Au retour de
new, elle va faire « return p + quelqueChose », et la première
chose qu'elle va faire en delete, c'est « p = obj -
quelqueChose », pour pouvoir accéder à l'en-tête.

--
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
Jean-Marc Bourguet
nico writes:

Jean-Marc Bourguet wrote:

nico writes:

Comment "delete" connait-il la taille du block à désallouer ?


Il doit le deduire de l'adresse passee.


Comment ?


C'est son probleme. Plusieurs techniques sont utilisees. Les deux
qui me viennent a l'esprit: stocker la taille avant et la deduire de
l'adresse (parce que l'adresse fait partie d'une zone utilisee pour
fournir des blocs de taille fixe).

Ceci par exemple est conforme:

void * rawptr = ::operator new(sizeof(A) + 20);
A* ptr = new(rawptr) A;
ptr->~A();
::operator delete(rawptr);

donc tu ne peux pas utiliser des informations de type.

D'ailleurs je me demande si

void * rawptr = ::operator new(sizeof(A) + 20);
A* ptr = new(rawptr) A;
ptr->~A();
delete rawptr;

ou

assert(sizeof(A) > sizeof(B));
A* ptr = new A;
ptr->~A();
B* ptrB = new(ptr) B
delete ptrB;

ou encore

void * rawptr = ::operator new(sizeof(A) + 20);
A* ptr = new(rawptr) A;
delete ptr;

ne le sont pas aussi.

--
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
nico
Salut,

Typiquement, l'implémentation va utiliser un en-tête au bloc,
avec toutes les informations dont elle a besoin. Au retour de
new, elle va faire « return p + quelqueChose », et la première
chose qu'elle va faire en delete, c'est « p = obj -
quelqueChose », pour pouvoir accéder à l'en-tête.


En fait actuellement j'utilise un systeme très simple :

char * block;
char * block_info;

block contient les données et block_info les données d'allocation, si bien
que si block_info[X]==0 alors block[X] est utilisable sinon block[X] est
utilisé.

Ce système a comme inconvénient majeur d'utiliser deux fois plus de mémoire
qu'il ne faudrait. (j'ai pensé stocker 8 infos par char (1 par bit) mais je
l'ai pas encore implementé)

Ensuite, à cause de ce problème de sizeof, je voulais changer pour un
système comme celui là :

typedef struct block_info
{
uint address; //adresse du block
size_t size; //longueur

} block_info;

char * data;
block_info * infos;

mais la idem, si on alloue bcp de petits blocks ce n'est pas rentable (on
gache trop de mémoire).

Je n'avais pas pensé, par contre, à un système d'entête comme tu le
suggères, j'avoue que ca serait une bonne idée car on a plus à stocker
l'adresse, et donc, si j'ai bien compris ce que tu as voulu dire, un block
aurait cette tete :

[[taille sur un int][data]]

Je vais essayer comme ca (sauf si vous avez encore mieux :) ).

--
nico

Avatar
nico
Erratum :
[[taille sur un int][data]]
sur un unsigned int :) (ou size_t qui doit revenir au même).


--
nico

Avatar
Patrick 'Zener' Brunet
Bonjour.

Bonjour,

Comment "delete" connait-il la taille du block à désallouer ?
(question dans le cadre d'une surcharge de l'opérateur delete)


void operator delete(void * obj)
{
//ici sizeof(obj) renvoie une taille incorrecte
// dans le cadre d'héritage...
}



Il y a deux manières de l'envisager :
- soit le compilo maintient une base de données des adresses&tailles de
blocs, et génère lui-même lors de la libération l'information dont le
programmeur peut ainsi se dispenser,
- soit le mécanisme d'allocation maintient un header en tête de chaque bloc,
et il est assez facile dans un principe d'implémentation de se rendre compte
que cet entête :
- - ne peut se situer qu'au début du bloc (puisqu'à la libération sa taille
est encore inconnue),
- - doit exister pour les blocs libres et alloués (tant que des libres non
consécutifs ne peuvent pas être fusionnés : défragmentation),
- - doit contenir au moins (mais ça suffit formellement) ce statut du bloc +
sa taille complète (entête compris).

Donc typiquement l'allocation se fait sous la forme d'un bloc [taille
demandée + taille entête + déchet sacrifié], mais ensuite le mécanisme
d'allocation restitue un pointeur décalé à la fin de l'entête, lequel entête
restera donc "en dessous" des données de l'utilisateur. A la libération, le
décalage inverse permet de retrouver le début du bloc au sens "machine". Si
le bloc est libéré mais ne peut pas être fusionné car il est entouré de
blocs toujours alloués, alors l'ex-espace utilisateur est réutilisé pour y
loger des pointeurs de chaînage des blocs libres, en attendant donc la
libération d'un bloc contigu.
Il est possible aussi, en mode debug, de rajouter dans le déchet et dans
l'entête des marqueurs "sentinelles" dont l'intégrité est vérifiée à la
libération.

Il y a aussi un point important à ne pas négliger : l'allocation est
supposée fournir des pointeurs correctement alignés pour tout usage, ce qui
veut implique que la taille de l'entête doit être arrondie selon la règle
d'alignement la plus contraignante, ou bien pour éviter ce déchet-là, que le
mécanisme d'allocation travaille avec des pointeurs de blocs qui ne
respectent pas forcément cette règle. En tout cas l'utilisateur ne doit rien
voir de tout ça.

En C++, an niveau de l'opérateur new[], c'est encore plus compliqué parce
que le bloc retourné doit idéalement contenir un second entête pour
mémoriser le cardinal du tableau d'objets, afin qu'une implémentation de
delete[] (si on s'y risque) puisse s'y retrouver aussi.

Bref c'est assez sympa, il faut avoir implémenté ça une fois dans sa vie
pour avoir ensuite une juste idée des conséquences de ses choix
"d'utilisateur" sur le taux de moulinage.

Ca donne aussi une autre vision des performances à attendre de ces langages
prétendument merveilleux où l'on n'a plus à se préoccuper des pointeurs ;-)

Hope It Helps,

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/

Avatar
nico
Salut,

Il y a deux manières de l'envisager :
<snip>

Hope It Helps,


Merci pour ta réponse, c'est très interessant.
Je suis aussi d'accord sur le fait qu'il fau avoir implémenté ca ua moins
une fois dans sa vie :) C'est pour ca que je le fais :)

--
nico

1 2