Domanda

In C e C ++ assert è un molto di routine pesi massimi, scrivendo un errore stdout e chiude il programma. Nella nostra applicazione abbiamo implementato una sostituzione molto più robusto per affermare e dato il proprio macro. Ogni sforzo è stato fatto per sostituire assert con la nostra macro, ma ci sono ancora molti modi assert possono essere reintrodotti (per esempio, da librerie di terze parti interne, iniezione ingenuo, ecc.)

Qualche suggerimento su come possiamo ridurre, limitare o addirittura eliminare usi di assert? La migliore risposta sarà uno il compilatore può prendere per noi, così non abbiamo da babysitter alla base di codice, come piace a noi al momento.

È stato utile?

Soluzione

Io non sono sicuro di aver ben capito il problema, in realtà. Afferma sono solo costoso se se ne vanno, che va bene in ogni caso, dal momento che siete ora in una situazione di eccezione.

assert è abilitata solo nel build di debug, in modo da utilizzare la build di rilascio di una libreria di terze parti. Ma in realtà, afferma non dovrebbe essere andare fuori ogni momento.

Altri suggerimenti

Può essere utile per migliorare l'impianto asserzione built-in (per fornire tracce di stack, core dump, chi lo sa). In tal caso, se si hanno problemi per ottenere gli sviluppatori a seguire tutto ciò che gli standard si dispone (come "invece di utilizzare assert() SUPER_ASSERT()" o qualsiasi altra cosa), si può semplicemente mettere il proprio colpo di testa assert.h nel percorso di inclusione davanti directory di runtime del compilatore di intestazioni.

che sarà più o meno la garanzia che chiunque utilizzi la macro assert() serie otterrà un errore di compilazione o di ottenere la funzionalità affermazione (a seconda di ciò che avete la vostra intestazione assert.h fare).

E 'dipenderebbe (almeno in parte) su ciò che si sta modificando. Supponendo che non ti dispiace che la stampa il suo messaggio normale, e soprattutto vuole sbarazzarsi di esso chiamando abort(), si potrebbe considerare di lasciare assert() da sola, e invece definire la propria versione di abort().

In teoria, facendo che non è portabile - ma in realtà, abort() è una funzione abbastanza normale nella libreria standard, e se si collega il proprio, invece, si ottiene il suo comportamento. A volte (in particolare alcuni linker Microsoft) si deve fare un po 'di lavoro per ottenere il linker a collaborare per sostituire il loro abort() con la vostra, ma è raramente molto difficile.

Credo che la tua domanda è del tutto valido. Se si è implementato il proprio la gestione degli errori si consiglia di:

  1. Sempre grilletto afferma anche nelle build di rilascio.
  2. Implementare una migliore segnalazione degli errori nel caso in cui un'asserzione innesca. Si consiglia di inviare segnalazioni di errori o scrivere file di log.

Detto questo, non vedo alcuna soluzione che funziona sempre.

  • Se si è fortunati, le librerie di terze parti utilizzano le macro affermare che è possibile ridefinire se stessi fino a quando il file di definizione di questa macro ha una sorta di #pragma once o #ifndef __HEADERFILE_H__ #define __HEADERFILE_H__ disposizione contro inclusione multipla. Includere il file di intestazione separatamente, ridefinire affermare e si sta bene.

  • Se si includono direttamente o assert.h cassert si può solo correggere il codice immagino. Fare minime modifiche al codice, salvare le modifiche come file di patch e quando si aggiorna la libreria sperare che i cerotti funzionano ancora. Aggiungere le patch per il controllo di versione.

Se questo non funziona, ripensare la questione se si ha realmente bisogno interno afferma in librerie di terze parti. rilascio della nave costruisce solo, questo si libera del afferma, e aggiungere il vostro afferma di controllare la correttezza all'interno del vostro codice. Verificare la validità dei valori di ritorno. Se tale ASSERT viene attivato, è comunque possibile tuffarsi nel codice di terze parti per vedere che cosa ha causato il problema.

Credo che la domanda è valida.

Il mio molto proprio assert espande per asm ( "int3"), se attivato, che equivale a un punto di interruzione. Ho anche scoperto che di gran lunga più utile per il debug di una semplice terminazione.

ho semplicemente chiamato "ASSERT ()" invece del normale "assert ()" ed evitato l'uso di assert () a tutti.

L'approccio più ovvio sembrerebbe essere per dare la propria versione di affermare il proprio nome, un po 'diverso da assert(). Poi si può cercare il testo, guardare i messaggi di linker, ecc, per il "_assert" stringa letterale e sai di avere un problema quando lo vedi.

Nel mio codice, io uso sempre Assert(), che si espande per la mia funzione che esegue un'affermazione, o si espande a ((void)0) per il build di rilascio. Il compilatore si accende l'espressione ((void)0) nel nulla, ma conta ancora come espressione. Così

Assert(3 == x);

si trasformerà in

((void)0);

e il punto e virgola ha un posto dove andare.

A proposito, una volta ho lavorato su un'applicazione GUI in cui l'asserzione era una finestra pop-up speciale GUI modale. Hai avuto tre scelte: Ignora, Ignora per sempre, o rompersi. Ignorare ignorerebbe l'asserzione e continuare a correre. Ignora sempre fisserebbe una bandiera, e fino a quando riavviato il programma nel debugger, che affermano non avrebbe sparato più. Pausa permetterebbe l'asserzione per passare al debugger.

Non mi ricordo come hanno garantito che ogni asserzione aveva la sua bandiera. Forse quando hai scritto l'Assert () chiamata è stato necessario specificare un numero intero univoco? Sarebbe bello se fosse più automatico di quello. Sono abbastanza sicuro che l'implmentation reale era un vettore di bit, e sarebbe impostare il bit quando si è scelto di ignorare per sempre.

assert() è di solito #define'd essere ((void) 0) per il codice di rilascio (#define NDEBUG), per cui v'è non appesantisce affatto .

Quando si utilizza una versione di prova, è il sovraccarico di prestazioni danneggiare la vostra capacità per il test per essere realistici?

Sembra che tu stia mancando il fatto che il codice di terze parti è molto probabilmente scritto sotto l'ipotesi di un comportamento "standard" assert. Cioè il codice prevede che il programma per terminare sulla asserzione fallita. Il codice che segue l'asserzione normalmente non può e non funziona correttamente se la condizione affermato è rotto. In 99 casi su 100 non funzionerà affatto. In 99 casi su 100 andrà in crash semplicemente, vale a dire il programma terminerà in ogni caso.

Per credere che l'override del comportamento assert nel codice di terze parti si in qualche modo rendere il programma di vivere più a lungo è ingenuo nel migliore dei casi.

Se il codice sorgente è sotto il vostro controllo:

#define NDEBUG
// Before
#include <assert.h>
// Or other header that includes assert.h

o utilizzando intestazione precompilata o compilare le opzioni per definire NDEBUG.

Per i binari di terze parti, utilizzare la versione di rilascio di loro.

Trova assert nelle intestazioni di libreria (ammesso che siano reali i file sul vostro file system) e sostituirlo con una cosa non valida

// #define assert(condition) ... /* old definition */
#define assert(condition) ((condition) & "PLEASE DO NOT USE ASSERT" = 42)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top