Est-il possible de marquer un segment de mémoire « hors limites » de sorte que le gestionnaire tas n'alloue pas de lui?

StackOverflow https://stackoverflow.com/questions/4274058

Question

Aujourd'hui, j'ai demandé cette question .

Après avoir passé quelque temps à enquêter sur cette question, je l'ai découvert ce qui se passe. Je signale cela comme une nouvelle question parce que je pense qu'il est assez intéressant de suivre comme une question distincte. Je mettrai à jour cette question avec la réponse (et un lien vers celui-ci).

Lancement de test unitaire de débogueur

// Construct object
Object* pObject = new Object(...);
// Pointer value of pObject == 0x05176960

// Lots of other code
// ...

// Destroy object
delete pObject;

// Construct object again
pObject = new Object(...);
// Pointer value of pObject == 0x05560194     /* Different memory location */

Lancement de test unitaire de ligne de commande

// Construct object
Object* pObject = new Object(...);
// Pointer value of pObject == 0x05176960

// Lots of other code
// ...

// Destroy object
delete pObject;

// Construct object again
pObject = new Object(...);
// Pointer value of pObject == 0x05176960     /* Same memory location */

En résumé:

  • Lors du lancement du test unitaire de la ligne de commande , les appels suivants à new d'allouer un Object (deleteing la Object précédente avant d'allouer un nouveau) reviennent toujours même adresse en mémoire.
  • Lors du lancement du test unitaire du débogueur , les appels suivants à new d'allouer un Object (deleteing la Object précédente avant d'allouer un nouveau) reviennent toujours uniques adresse en mémoire.

Le problème est que parce que les allocations de Object toujours obtenir la même adresse en mémoire lors du lancement par la ligne de commande, une carte que j'accède qui a enregistré le vieux pointeur peut toujours être utilisé et test ne sera pas tomber en panne. Mais je veux que mon test unitaire plantage lorsque le correctif de défaut est pas en place, pour faire en sorte que cela ne faillir en silence et le défaut ne revient pas.

Il y a 2 parties à ma question:

  1. Pourquoi le gestionnaire de tas réutilise la même partie de la mémoire lors du lancement d'un test unitaire de la ligne de commande, mais pas quand je lancer le test unitaire du débogueur?

  2. Y at-il un paramètre compilateur je pourrais utiliser sur mon harnais de test, ou une méthode, je peux appeler pour empêcher le gestionnaire de tas de réutiliser une partie de la mémoire que j'ai supprimé, pour me permettre d'écrire correctement mon Test de l'unité? 1


1 Il est évident qu'une façon de le faire est de ne pas supprimer l'objet d'origine, mais la partie du code qui attribue cela est dans mon code de production, et je faire cela entraînerait des fuites de mémoire.

Était-ce utile?

La solution

Votre test unitaire est erronée, car il est sur le comportement reposant non défini. Vous devez réécrire votre test unitaire afin qu'elle ne repose pas sur le comportement non défini, dans ce cas, il sera toujours passer, peu importe la façon dont le gestionnaire de mémoire décide d'allouer de la mémoire.

Ce que vous faites est la suivante:

Object* pObject = new Object(...);
...
delete pObject;
pObject = new Object(...);
// Use dangling pointer to first object, and if it crashes, the unit test fails
// This is WRONG since a crash isn't guaranteed

Vous devriez plutôt restructurer le test unitaire de sorte qu'il fonctionne comme ceci:

Object* pObject = new Object(...);
...
// Check to see if there are dangling references to pObject right before we
// delete it.  If there are, assert() and fail the unit test.
assert(NoDanglingReferences(pObject));
delete pObject;
// Continue on with more tests

Autres conseils

Vous pourriez remplacer new et delete avec vos propres versions qui ont le comportement que vous voulez.

D'abord - pas dans un gestionnaire de mémoire « normale ». Une fois que vous désallouer la mémoire vous passez la propriété de celui-ci au gestionnaire de mémoire et celui-ci peut le réutiliser.

Vous pourriez Andreas Brinck suggère le tas-manager / 4274140 # 4274140" > écrire un gestionnaire personnalisé , mais que ferait-il? Il ne la mémoire de l'artisanat de l'air, il lui demande de quelque part comme tas CRT ou tas de système d'exploitation.

Scénario A. Il ne reviendra pas mémoire sur le tas sous-jacente -. Vous aurez une fuite et le bloc de mémoire sera toujours mis en correspondance l'espace d'adressage et il sera accessible

Scénario B. Il retournera mémoire tas sous-jacente - alors quand votre mananger tente d'allouer de la mémoire à nouveau le tas sous-jacente peut retourner ce bloc à nouveau. Aussi, vous ne savez pas ce que le tas sous-jacent fait quand vous revenez mémoire à elle. Il pourrait faire Unmapped ou non -. Si l'accès à cette mémoire peut se bloquer ou non

L'essentiel est que vous êtes foutus. Essayer de tester le comportement non défini ne va pas être très productif.

Ceci est un exemple de UNDEFINED COMPORTEMENTS. Ni C ++ ou le gestionnaire de tas définissent la façon dont la mémoire va être alloué. Vous ne pouvez pas compter sur la mémoire soit réutilisée ou non être réutilisé. Quand vous faites quelque chose comme dans ce qui précède, il n'y a aucun moyen de déterminer ou modifier si oui ou non le pointeur de retour sera différent du premier alloué.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top