OVH Cloud OVH Cloud

trace memoire

3 réponses
Avatar
dug
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 )
{

void *ptr = (void *)malloc(size + TraceSize);
if( ptr == 0 ) throw std::bad_alloc();

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. ;)

3 réponses

Avatar
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 )
{

void *ptr = (void *)malloc(size + TraceSize);
if( ptr == 0 ) throw std::bad_alloc();

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. ;)


Avatar
dug
wrote in news:1105092159.058208.141980
@z14g2000cwz.googlegroups.com:


void* Allouer(std::size_t size, const char *file, int line )
{

void *ptr = (void *)malloc(size + TraceSize);
if( ptr == 0 ) throw std::bad_alloc();

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.


Avatar
kanze
dug wrote:
wrote in news:1105092159.058208.141980
@z14g2000cwz.googlegroups.com:

void* Allouer(std::size_t size, const char *file, int line )
{

void *ptr = (void *)malloc(size + TraceSize);
if( ptr == 0 ) throw std::bad_alloc();

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