E 'possibile marcare un segmento della memoria come “fuori dai limiti” in modo che il gestore degli heap non alloca da esso?

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

Domanda

Proprio oggi ho chiesto a questa domanda .

Dopo aver trascorso qualche tempo approfondendo il problema, ho scoperto che cosa sta succedendo. Sto inviando questo come una nuova domanda, perché penso che sia abbastanza interessante per monitorare come una questione separata. I aggiornerà questa domanda con la risposta (e un link a questo).

Avvio prova di unità da debugger

// 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 */

Avvio prova di unità da linea di comando

// 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 */

In sintesi:

  • Quando si avvia il test unità dalla riga di comando , chiamate successive new per allocare un Object (deleteing la Object precedente prima di allocare uno nuovo) restituiscono sempre il stesso indirizzo nella memoria.
  • Quando si avvia il test unità dalla debug , chiamate successive new per allocare un Object (deleteing la Object precedente prima di allocare una nuova) restituiscono sempre un unico indirizzo in memoria.

Il problema è che a causa assegnazioni di Object ottenere sempre lo stesso indirizzo in memoria quando si lancia attraverso la linea di comando, una mappa che io sono l'accesso che ha memorizzato il vecchia puntatore può essere ancora utilizzati e la test non andrà in crash. Ma io voglio che il mio test di unità in crash quando la correzione difetto non è a posto, al fine di garantire che non si fallire in modo silenzioso e il difetto non torna.

Ci sono 2 parti alla mia domanda:

  1. Perché il gestore di heap ri-usare la stessa parte della memoria quando si avvia un test di unità dalla riga di comando, ma non quando lanciare il test di unità dal debugger?

  2. C'è una impostazione ho potuto usare il mio test harness, o un metodo che può chiamare per evitare che il gestore di heap da compilatore ri-utilizzando una sezione di memoria che ho cancellato, per permettere a me di scrivere correttamente il mio unit test? 1


1 Ovviamente un modo per farlo è di non eliminare l'oggetto originale, ma la parte del codice che alloca questo è nel mio codice di produzione, e facendo questo si tradurrebbe in perdite di memoria.

È stato utile?

Soluzione

Il test di unità è viziata, dal momento che è fare affidamento su un comportamento indefinito. Si dovrebbe riscrivere il vostro test di unità in modo che non si basa su un comportamento indefinito, nel qual caso sarà sempre passare a prescindere da come il gestore della memoria decide di allocare la memoria.

Quello che stai facendo è questo:

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

Si dovrebbe invece ristrutturare il test di unità in modo che funziona in questo modo:

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

Altri suggerimenti

Si potrebbe sostituire new e delete con le proprie versioni che hanno il comportamento desiderato.

Prima di tutto - non in un "normale" gestore della memoria. Una volta che si deallocare memoria si passa la proprietà di esso per il gestore della memoria e il secondo poterlo riutilizzare.

Si potrebbe scrivere un manager personalizzato come Andreas Brinck suggerisce , ma cosa farebbe? E non lo fa memoria del mestiere da aria, richiede da qualche parte come CRT heap o operativo mucchio di sistema.

Scenario A. Non sarebbe tornare la memoria al mucchio di fondo -. Avrai una perdita e il blocco di memoria sarà ancora mappato nello spazio di indirizzi e sarà accessibile

Scenario B. Si tornerà alla memoria heap sottostante - poi quando il tuo mananger tenta di allocare la memoria ancora una volta il valore sottostante mucchio può tornare di nuovo quel blocco. Inoltre non si sa che cosa il mucchio sottostante fa quando si torna la memoria ad esso. Si potrebbe rendere non mappati o no -. In modo che la memoria accesso potrebbe bloccarsi o non

La linea di fondo è sei fregato. Cercando di testare indefinito comportamento non sta andando essere molto produttivo.

Questo è un esempio di UNDEFINED comportamento. Né C ++ o il gestore di heap definiscono come memoria sta per essere assegnato. Non si può contare su entrambi memoria che è riutilizzato o non essere riutilizzato. Quando fai qualcosa di simile a quanto sopra, non v'è alcun modo per determinare il cambiamento o se il puntatore restituito sarà diverso dal primo allocato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top