Domanda

Di tanto in tanto si incontrano bug che sono riproducibili solo nei build di rilascio e / o solo su alcune macchine. Un comune (ma non per questo solo) ragione è inizializzato variabili, che sono soggette a comportamento casuale. Per esempio, un BOOL inizializzato può essere TRUE maggior parte del tempo, sulla maggior parte delle macchine, ma casualmente essere inizializzato come FALSE.

Quello che mi auguro che avrei è un modo sistematico di stanare questi bug modificando il comportamento della inizializzazione della memoria CRT. Sono ben consapevole dei MS di debug CRT numeri magici - per lo almeno Vorrei avere un grilletto per accendere 0xCDCDCDCD (il modello che inizializza appena allocata memoria) di zeri. Ho il sospetto che uno sarebbe in grado di fumare facilmente fuori brutto parassiti di inizializzazione in questo modo, anche in build di debug.

mi manca un gancio a disposizione CRT (API, chiave di registro, a prescindere) che permette a questo? Chiunque ha altre idee per arrivare?

[Edit:] Sembra chiarimenti sono in ordine.

  1. I numeri magici soliti infatti hanno molti vantaggi, ma non forniscono la copertura per inizializzazioni bool (sempre vero), o campi di bit che vengono testati contro singoli maschere di bit, o in casi simili. Coerente a zero inizializzazione (che sono in grado di attivare o disattivare, ovviamente), sarebbe aggiungere uno strato di prova che possono emergere comportamento init cattivo che può essere raro altrimenti.
  2. sono consapevoli, naturalmente, di CrtSetAllocHook . Il gancio così impostato non riceve un puntatore al buffer allocato (si chiama prima come tampone è stato allocato), quindi non può sovrascrivere. Sovraccarico globale nuova non farebbe tanto bene, come sarebbe sovrascrivere qualsiasi inizializzazione del costruttore valido.

[Edit:] @ Michael, non so cosa si intende per l'override nuova. semplice codice come -

void* new(...)
{
   void* res = ::new(...);   // constructors now called!
   if(SomeExternalConditionApplies())
      OverWriteBufferWithMyPetValues(res);
}

non avrebbe funzionato. Incollare e modificando l'intera :: nuovo lavoro codice potrebbe, ma sembra un po 'paura (Dio solo sa che cosa avrei dovuto #include e link per farlo funzionare).

È stato utile?

Soluzione

Non ti seguo - vista insieme alla memoria non inizializzata a qualcosa di simile 0xcdcdcdcd invece di 0 è migliore per stanare i bug, perché il codice è più probabile ottenere 'nella gamma' aritmetica o appositamente gestire 0. con il valore selvaggiamente valido, gli insetti sono più probabilità di 'fallire veloce' in modo che possano essere fissati al posto di nascosto.

I valori che la build di debug di usi MSVC sono specificamente progettati per i guasti aiuto cause che possono essere facilmente rilevabili:

  • non sono 0, quindi controlli puntatore nullo nei confronti di memoria non inizializzata non nasconde il bug
  • non sono puntatori validi, quindi dereferenziazione puntatori non inizializzati causerà una violazione di accesso
  • non sono 'solito' intero valori, in modo da calcoli che coinvolgono dati non inizializzati di solito portare a risultati non corretti selvaggiamente che tenderanno a causare errori evidenti (penso che sia negativo quando trattati come dati firmati aiuta anche un po 'con questo, ma non tanto quanto semplicemente essere numeri insoliti).

Inoltre, sono facili da riconoscere nei display dati nel debugger. Zero non si distinguono quasi più.

Tutto ciò che ha detto, MSVC fornisce una serie di ganci di debug / API che si potrebbe essere in grado di utilizzare per fare qualcosa sulla falsariga di ciò che si vuole:

Alcune informazioni aggiuntive in risposta alla tua domanda aggiornamento:

Si potrebbe essere in grado di utilizzare una terza libreria di allocazione del partito di debug come dmalloc ( http://dmalloc.com/), ma onestamente non so quanto sia facile queste librerie sono da integrare in un progetto MSVC, specialmente 'mondo reale' quelli.

Si noti inoltre che questi, ovviamente, saranno trattati solo con le allocazioni dinamiche (e potrebbero non integrarsi bene con implementazione predefinita new di MSVC).

possono usare una sostituzione globale di operator new() a che fare con le allocazioni che si verificano utilizzando new in C ++ - non c'è un problema con sovrascrivendo eventuali inizializzazioni costruttore validi - l'assegnazione new si verifica prima che le esegue costruttore qualsiasi inizializzazione (se ci pensate per un momento dovrebbe essere chiaro perché questo è).

Inoltre, si potrebbe prendere in considerazione di trasferirsi a Visual Studio 2010 - sarà passare al debugger quando si utilizza una variabile locale non inizializzata - non fare nulla di speciale diverso da quello che esegue la build di debug nel debugger. Naturalmente, MSCV ha messo in guardia su molte di queste situazioni per un po ', ma VS2010 prenderà la seguente nel debugger, che produce nessun avviso (almeno con le mie impostazioni del compilatore correnti):

int main(  )
{
    unsigned int x;
    volatile bool a = false;

    if (a) {
        x = 0;
    }

    printf( "Hello world %u\n", x); // VS2010 will break here because x is uninitialized

    return 0;
}

Anche la versione Express di VC ++ 2010 supporta questo.

Altri suggerimenti

Solo un suggerimento: si può utilizzare lo strumento di analisi statica del codice nel vostro compilatore? / Analizzare vi darà un messaggio di avviso C6001 che si sta utilizzando la memoria non inizializzata. Ed è un po 'sistematica, che è ciò che il vostro chiedendo.

Entrando gli spettacoli CRT i numeri magici sono utilizzati in _heap_alloc_dbg e realloc_help, e il valore stesso viene codificato come

static unsigned char _bCleanLandFill  = 0xCD;   /* fill new objects with this */

Conoscere che cosa cercare spesso aiuta . Il filo collegato ha una bella suggerimento: impostare un orologio sul _bCleanLandFill e modificarlo dal debugger.

Si fa il lavoro, ma terrò questa questione aperta per un po '- ho ancora sperare che qualcuno ha un'idea migliore ... Speravo di eseguire test automatizzati con inizializzazioni controllate, e non hanno a che fare manualmente (e solo con un debugger a disposizione).

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