2010-11-01 7 views

Répondre

8

Vous ne pouvez pas le faire en tout temps, car operator new() peut être surchargée de quelque façon raisonnable et peut-être même sans utiliser le tas d'exécution.

Dans le cas où operator new() est implémenté avec malloc() dans Visual C++, vous pouvez utiliser _msize().

5

Bien que Sharptooth a raison dans sa réponse (nouveau peut être surchargé), la solution pourrait être juste dans ce fait. En surchargeant new, vous pouvez facilement ajouter votre propre implémentation de new et delete. Dans votre mise en œuvre d'une nouvelle, vous devez:

  • EDIT: autour de la taille au multiple de 8 octets
  • ajouter 8 octets à la taille demandée par l'application
  • appel à la mémoire des systèmes allouer routine (par exemple HeapAlloc sous Windows)
  • remplissage de la taille initialement demandée dans les 8 premiers octets
  • ajouter 8 au pointeur retourné et retourner ce à l'application

L'opérateur delete doit faire le contraire:

  • Soustraire 8 octets du pointeur données par l'application
  • appel systèmes mémoire de routine deallocate

Si vous le faites de cette façon, assurez-vous d'implémenter toutes les saveurs de new et delete (lancer et non-lancer, nouveau et nouveau [], supprimer et supprimer [], ...).

Faites également attention aux bibliothèques tierces. Ils placent parfois l'appel à nouveau dans leur code compilé dans leur DLL, mais l'appel à supprimer dans l'en-tête. Cela signifie que new et delete utiliseront des implémentations différentes et que votre application va planter.

EDIT:

L'arrondi au multiple de 8 octets et l'ajout de 8 octets est nécessaire parce que les données doivent être stockées à un addres qui est un multiple de sa taille:

  • les caractères peuvent être stockés plus
  • short doivent être stockés sur une adresse même
  • désire ardemment doivent être stockés sur une adresse qui est un multiple de 4
  • doubles doivent être stockés sur une adresse qui est un multiple de 8

Depuis doubles sont le plus grand type de données natif que je suis au courant, nous arrondissons à un multiple de 8 octets et nous ajoutons 8 octets pour faire Assurez-vous de garder ces exigences.

+1

Pourquoi exactement 8 octets et pas "assez d'octets pour stocker une variable' size_t' "? – sharptooth

+0

Parce que les types de données natifs doivent être stockés sur une adresse qui est un multiple de sa taille. Normalement, le plus grand type de données est double, soit 8 octets. Par conséquent, nous devons ajouter 8 octets à la taille et au pointeur pour garder un multiple de 8 octets. (ajoutez une légère correction à mon article pour vous assurer que nous gardons ces multiples de 8 octets). – Patrick

+0

D'accord, je vois. Alors ne devrait-il pas être 'max (sizeof (double), sizeof (void *))' ou quelque chose comme ça pour que le code soit portable sur les ordinateurs bit 1024 (ou peu importe)? – sharptooth

1
  • Vous pouvez réécrire l'opérateur new appeler malloc() et stocker la taille dans une std::map<void*, size> alloc mondiale.

Ensuite, cette fonction getSomeHow() se comportera comme vous voulez:

getSomeHow(void *p){ 
    return alloc[p]; 
} 
  • Vous pouvez également écrire votre propre malloc() et mettre le chargeur à utiliser votre malloc au lieu du standard. Je l'ai fait pour le but de traçage, cela fonctionne très bien.
+0

C'est génial, mais pourquoi ne pas simplement allouer un bloc un peu plus grand, écrire la taille allouée à son début et retourner un pointeur de décalage? – sharptooth

+0

Hum oui, c'est beaucoup mieux en fait! – Ben

+0

@Ben pourriez-vous s'il vous plaît fournir un indice sur la façon d'écrire mon propre malloc? Cela m'intéresse beaucoup. Merci d'avance –

Questions connexes