Bonjour, dans le but de tracer les allocations memoires,
j'ai écris un petit programme qui redéfinit les opérateurs
new et delete globaux avec malloc et free.
Pour pouvoir tracer les allocations des blocs je reserve
un peu plus de memoire qu'il me faut et j'écris un compteur
à cet emplacement mémoire.
tout ça à l'air de bien fonctionner mais j'ai un doute sur
la façon dont je l'ai fait.
voila la fonction allouer qui reserve la memoire:
// le compteur est une union de char[4] et de int
// Tracesize = sizeof( l'union ci dessus )
void* Allouer(std::size_t size, const char *file, int line )
{
unsigned char* cptr = static_cast<unsigned char*>( ptr);
mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ;
TraceAllocation(cptr, mCount.Int(), size, file, line);
return (cptr + TraceSize);
}
Je créé un objet avec new, qui appelle cette fonction.
Mon doute est que j'écris mon compteur à partir de l'adresse ptr
qui est réservée pour l'objet que je créé, est-ce qu'il ne risque
pas d'y avoir un mélange de données ( entre le compteur et l'objet?),
ou est-ce que l'objet va se ranger juste après ?
Ca dépend du système d'exploitation ?
je suis sous windows et j'utilise g++ (via Devcpp).
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
kanze
dug wrote:
Bonjour, dans le but de tracer les allocations memoires, j'ai écris un petit programme qui redéfinit les opérateurs new et delete globaux avec malloc et free.
Pour pouvoir tracer les allocations des blocs je reserve un peu plus de memoire qu'il me faut et j'écris un compteur à cet emplacement mémoire.
tout ça à l'air de bien fonctionner mais j'ai un doute sur la façon dont je l'ai fait.
voila la fonction allouer qui reserve la memoire:
// le compteur est une union de char[4] et de int // Tracesize = sizeof( l'union ci dessus ) void* Allouer(std::size_t size, const char *file, int line ) {
unsigned char* cptr = static_cast<unsigned char*>( ptr); mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ; TraceAllocation(cptr, mCount.Int(), size, file, line); return (cptr + TraceSize); }
Je créé un objet avec new, qui appelle cette fonction.
Mon doute est que j'écris mon compteur à partir de l'adresse ptr qui est réservée pour l'objet que je créé, est-ce qu'il ne risque pas d'y avoir un mélange de données ( entre le compteur et l'objet?),
ou est-ce que l'objet va se ranger juste après ? Ca dépend du système d'exploitation ?
je suis sous windows et j'utilise g++ (via Devcpp).
merci pour vos réponses. ;)
dug wrote:
Bonjour, dans le but de tracer les allocations memoires,
j'ai écris un petit programme qui redéfinit les opérateurs
new et delete globaux avec malloc et free.
Pour pouvoir tracer les allocations des blocs je reserve
un peu plus de memoire qu'il me faut et j'écris un compteur
à cet emplacement mémoire.
tout ça à l'air de bien fonctionner mais j'ai un doute sur
la façon dont je l'ai fait.
voila la fonction allouer qui reserve la memoire:
// le compteur est une union de char[4] et de int
// Tracesize = sizeof( l'union ci dessus )
void* Allouer(std::size_t size, const char *file, int line )
{
unsigned char* cptr = static_cast<unsigned char*>( ptr);
mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ;
TraceAllocation(cptr, mCount.Int(), size, file, line);
return (cptr + TraceSize);
}
Je créé un objet avec new, qui appelle cette fonction.
Mon doute est que j'écris mon compteur à partir de l'adresse ptr
qui est réservée pour l'objet que je créé, est-ce qu'il ne risque
pas d'y avoir un mélange de données ( entre le compteur et
l'objet?),
ou est-ce que l'objet va se ranger juste après ?
Ca dépend du système d'exploitation ?
je suis sous windows et j'utilise g++ (via Devcpp).
Bonjour, dans le but de tracer les allocations memoires, j'ai écris un petit programme qui redéfinit les opérateurs new et delete globaux avec malloc et free.
Pour pouvoir tracer les allocations des blocs je reserve un peu plus de memoire qu'il me faut et j'écris un compteur à cet emplacement mémoire.
tout ça à l'air de bien fonctionner mais j'ai un doute sur la façon dont je l'ai fait.
voila la fonction allouer qui reserve la memoire:
// le compteur est une union de char[4] et de int // Tracesize = sizeof( l'union ci dessus ) void* Allouer(std::size_t size, const char *file, int line ) {
unsigned char* cptr = static_cast<unsigned char*>( ptr); mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ; TraceAllocation(cptr, mCount.Int(), size, file, line); return (cptr + TraceSize); }
Je créé un objet avec new, qui appelle cette fonction.
Mon doute est que j'écris mon compteur à partir de l'adresse ptr qui est réservée pour l'objet que je créé, est-ce qu'il ne risque pas d'y avoir un mélange de données ( entre le compteur et l'objet?),
ou est-ce que l'objet va se ranger juste après ? Ca dépend du système d'exploitation ?
je suis sous windows et j'utilise g++ (via Devcpp).
merci pour vos réponses. ;)
dug
wrote in news:1105092159.058208.141980 @z14g2000cwz.googlegroups.com:
void* Allouer(std::size_t size, const char *file, int line ) {
unsigned char* cptr = static_cast<unsigned char*>( ptr); mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ; TraceAllocation(cptr, mCount.Int(), size, file, line); return (cptr + TraceSize); }
J'ai pas bien saisi la réponse :o)
En y réfléchissant, je crois que la réponse est dans ma question.
Reprenez moi si je dis une ânerie: Si j'alloue (size + tracesize) de place mémoire à l'adresse cptr, j'utilise le début de la mémoire allouée sur la plage (0,tracesize) pour numéroter le bloc mémoire, et je retourne le reste de mémoire allouée sur la plage ( tracesize, tracesize+size) qui a pour adresse de début cptr + Tracesize.
kanze@gabi-soft.fr wrote in news:1105092159.058208.141980
@z14g2000cwz.googlegroups.com:
void* Allouer(std::size_t size, const char *file, int line )
{
unsigned char* cptr = static_cast<unsigned char*>( ptr);
mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ;
TraceAllocation(cptr, mCount.Int(), size, file, line);
return (cptr + TraceSize);
}
J'ai pas bien saisi la réponse :o)
En y réfléchissant, je crois que la réponse est dans ma question.
Reprenez moi si je dis une ânerie:
Si j'alloue (size + tracesize) de place mémoire à l'adresse cptr, j'utilise le début
de la mémoire allouée sur la plage (0,tracesize)
pour numéroter le bloc mémoire, et je retourne le reste de mémoire allouée sur la
plage ( tracesize, tracesize+size) qui a pour adresse de début cptr + Tracesize.
unsigned char* cptr = static_cast<unsigned char*>( ptr); mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ; TraceAllocation(cptr, mCount.Int(), size, file, line); return (cptr + TraceSize); }
J'ai pas bien saisi la réponse :o)
En y réfléchissant, je crois que la réponse est dans ma question.
Reprenez moi si je dis une ânerie: Si j'alloue (size + tracesize) de place mémoire à l'adresse cptr, j'utilise le début de la mémoire allouée sur la plage (0,tracesize) pour numéroter le bloc mémoire, et je retourne le reste de mémoire allouée sur la plage ( tracesize, tracesize+size) qui a pour adresse de début cptr + Tracesize.
kanze
dug wrote:
wrote in news:1105092159.058208.141980 @z14g2000cwz.googlegroups.com:
void* Allouer(std::size_t size, const char *file, int line ) {
unsigned char* cptr = static_cast<unsigned char*>( ptr); mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ; TraceAllocation(cptr, mCount.Int(), size, file, line); return (cptr + TraceSize); }
J'ai pas bien saisi la réponse :o)
C'est parce que le texte que j'avais ajouté s'est perdu quelque part. (Je poste souvent à travers Google, et ils sont en train de faire des modifications souvent en ce moment.)
Le principe de base, c'est que le compilateur ne sait rien de ce que tu fais dans la fonction operator new(). Tout ce qu'il a, c'est l'adresse que tu renvoies -- pour lui, c'est ça, le début du bloc alloué.
La deuxième chose que j'avais dit, c'est que ton code ne marche pas sur la plupart des machines, parce qu'il ne respecte pas l'alignement. La norme dit qu'une fonction operator new doit renvoyer une adresse suffisamment alignée pour tous les types de données. Sur ma machine, par exemple, ça veut dire une adresse multiple de 8. Or, tu prends l'adresse rétournée par malloc (elle aussi convenablement alignée pour touts les types, donc une multiple de 8), et tu en ajoutes 4. Sur un Sparc, ça garantit prèsque un core dump si tu y mets des doubles ; sur un Intel, il n'y aura pas de core dump, mais le programme s'exécutera d'une façon notablement moins rapide.
Enfin, je me suis posé la question sur ton histoire de memcpy (que tu émules en plus avec une boucle explicite). Moi, dans un cas pareil, je déclare quelque chose du genre :
union BlockHeader { int count ; MaxAlign dummyForAlignment ; } ;
void* operator new( size_t n ) { BlockHeader* p = malloc( n + sizeof( BlockHeader* ) ) ; if ( p == NULL ) { throw std::bad_alloc() ; } p->count = ++ mCount ; return p + 1 ; }
MaxAlign est défini comme un type qui a besoin de l'alignement maximal.
Enfin, je ne sais pas d'où tu espère tirer les paramètres de file et de line. (J'utilise une trace de pile dans mon propre code.)
En y réfléchissant, je crois que la réponse est dans ma question.
Reprenez moi si je dis une ânerie:
Si j'alloue (size + tracesize) de place mémoire à l'adresse cptr, j'utilise le début de la mémoire allouée sur la plage (0,tracesize) pour numéroter le bloc mémoire, et je retourne le reste de mémoire allouée sur la plage ( tracesize, tracesize+size) qui a pour adresse de début cptr + Tracesize.
C'est ce que tu fais dans ta fonction. Malheureusement, ta fonction n'est pas correcte en ce qui concerne la gestion de l'alignement, ni en ce qui concerne les paramètres à passer -- ta fonction ne sera appelée que dans le cas d'un new de placement.
-- James Kanze GABI Software http://www.gabi-soft.fr 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
dug wrote:
kanze@gabi-soft.fr wrote in news:1105092159.058208.141980
@z14g2000cwz.googlegroups.com:
void* Allouer(std::size_t size, const char *file, int line )
{
unsigned char* cptr = static_cast<unsigned char*>( ptr);
mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ;
TraceAllocation(cptr, mCount.Int(), size, file, line);
return (cptr + TraceSize);
}
J'ai pas bien saisi la réponse :o)
C'est parce que le texte que j'avais ajouté s'est perdu quelque
part. (Je poste souvent à travers Google, et ils sont en train
de faire des modifications souvent en ce moment.)
Le principe de base, c'est que le compilateur ne sait rien de ce
que tu fais dans la fonction operator new(). Tout ce qu'il a,
c'est l'adresse que tu renvoies -- pour lui, c'est ça, le début
du bloc alloué.
La deuxième chose que j'avais dit, c'est que ton code ne marche
pas sur la plupart des machines, parce qu'il ne respecte pas
l'alignement. La norme dit qu'une fonction operator new doit
renvoyer une adresse suffisamment alignée pour tous les types de
données. Sur ma machine, par exemple, ça veut dire une adresse
multiple de 8. Or, tu prends l'adresse rétournée par malloc
(elle aussi convenablement alignée pour touts les types, donc
une multiple de 8), et tu en ajoutes 4. Sur un Sparc, ça
garantit prèsque un core dump si tu y mets des doubles ; sur un
Intel, il n'y aura pas de core dump, mais le programme
s'exécutera d'une façon notablement moins rapide.
Enfin, je me suis posé la question sur ton histoire de memcpy
(que tu émules en plus avec une boucle explicite). Moi, dans un
cas pareil, je déclare quelque chose du genre :
union BlockHeader
{
int count ;
MaxAlign dummyForAlignment ;
} ;
void*
operator new( size_t n )
{
BlockHeader* p = malloc( n + sizeof( BlockHeader* ) ) ;
if ( p == NULL ) {
throw std::bad_alloc() ;
}
p->count = ++ mCount ;
return p + 1 ;
}
MaxAlign est défini comme un type qui a besoin de l'alignement
maximal.
Enfin, je ne sais pas d'où tu espère tirer les paramètres de
file et de line. (J'utilise une trace de pile dans mon propre
code.)
En y réfléchissant, je crois que la réponse est dans ma
question.
Reprenez moi si je dis une ânerie:
Si j'alloue (size + tracesize) de place mémoire à l'adresse
cptr, j'utilise le début de la mémoire allouée sur la plage
(0,tracesize) pour numéroter le bloc mémoire, et je retourne
le reste de mémoire allouée sur la plage ( tracesize,
tracesize+size) qui a pour adresse de début cptr + Tracesize.
C'est ce que tu fais dans ta fonction. Malheureusement, ta
fonction n'est pas correcte en ce qui concerne la gestion de
l'alignement, ni en ce qui concerne les paramètres à passer --
ta fonction ne sera appelée que dans le cas d'un new de
placement.
--
James Kanze GABI Software http://www.gabi-soft.fr
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
unsigned char* cptr = static_cast<unsigned char*>( ptr); mCount++;// variable static de classe
for( int i = 0; i <4; i++) cptr[i] = mCount.mc[i] ; TraceAllocation(cptr, mCount.Int(), size, file, line); return (cptr + TraceSize); }
J'ai pas bien saisi la réponse :o)
C'est parce que le texte que j'avais ajouté s'est perdu quelque part. (Je poste souvent à travers Google, et ils sont en train de faire des modifications souvent en ce moment.)
Le principe de base, c'est que le compilateur ne sait rien de ce que tu fais dans la fonction operator new(). Tout ce qu'il a, c'est l'adresse que tu renvoies -- pour lui, c'est ça, le début du bloc alloué.
La deuxième chose que j'avais dit, c'est que ton code ne marche pas sur la plupart des machines, parce qu'il ne respecte pas l'alignement. La norme dit qu'une fonction operator new doit renvoyer une adresse suffisamment alignée pour tous les types de données. Sur ma machine, par exemple, ça veut dire une adresse multiple de 8. Or, tu prends l'adresse rétournée par malloc (elle aussi convenablement alignée pour touts les types, donc une multiple de 8), et tu en ajoutes 4. Sur un Sparc, ça garantit prèsque un core dump si tu y mets des doubles ; sur un Intel, il n'y aura pas de core dump, mais le programme s'exécutera d'une façon notablement moins rapide.
Enfin, je me suis posé la question sur ton histoire de memcpy (que tu émules en plus avec une boucle explicite). Moi, dans un cas pareil, je déclare quelque chose du genre :
union BlockHeader { int count ; MaxAlign dummyForAlignment ; } ;
void* operator new( size_t n ) { BlockHeader* p = malloc( n + sizeof( BlockHeader* ) ) ; if ( p == NULL ) { throw std::bad_alloc() ; } p->count = ++ mCount ; return p + 1 ; }
MaxAlign est défini comme un type qui a besoin de l'alignement maximal.
Enfin, je ne sais pas d'où tu espère tirer les paramètres de file et de line. (J'utilise une trace de pile dans mon propre code.)
En y réfléchissant, je crois que la réponse est dans ma question.
Reprenez moi si je dis une ânerie:
Si j'alloue (size + tracesize) de place mémoire à l'adresse cptr, j'utilise le début de la mémoire allouée sur la plage (0,tracesize) pour numéroter le bloc mémoire, et je retourne le reste de mémoire allouée sur la plage ( tracesize, tracesize+size) qui a pour adresse de début cptr + Tracesize.
C'est ce que tu fais dans ta fonction. Malheureusement, ta fonction n'est pas correcte en ce qui concerne la gestion de l'alignement, ni en ce qui concerne les paramètres à passer -- ta fonction ne sera appelée que dans le cas d'un new de placement.
-- James Kanze GABI Software http://www.gabi-soft.fr 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