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
nico <nospam@spam.fr> 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
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
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
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
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
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
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
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).
-- 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
nico <nospam@spam.fr> writes:
Jean-Marc Bourguet wrote:
nico <nospam@spam.fr> 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).
--
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
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).
-- 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
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à :
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
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à :
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 :) ).
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à :
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
nico
Erratum :
[[taille sur un int][data]] sur un unsigned int :) (ou size_t qui doit revenir au même).
-- nico
Erratum :
[[taille sur un int][data]]
sur un unsigned int :) (ou size_t qui doit revenir au même).
[[taille sur un int][data]] sur un unsigned int :) (ou size_t qui doit revenir au même).
-- nico
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 ***************************************/
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
***************************************/
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 ***************************************/
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
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 :)
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 :)