Domanda

So che secondo lo standard C ++ nel caso in cui il nuovo non riesce a allocare la memoria che dovrebbe lanciare un'eccezione std :: bad_alloc. Ma ho sentito dire che alcuni compilatori, come VC6 (o implementazione CRT?) Non aderiscono ad esso. È vero ? Chiedo questo perché il controllo per NULL dopo ogni nuova dichiarazione rende il codice aspetto molto brutto.

È stato utile?

Soluzione

VC6 era non conforme per impostazione predefinita in questo senso. new di VC6 restituito 0 (o NULL).

Ecco l'articolo KB di Microsoft su questo tema insieme con la loro soluzione suggerita utilizzando un gestore new personalizzato:

Se si dispone di vecchio codice che è stato scritto per il comportamento VC6, è possibile ottenere lo stesso comportamento con le più recenti compilatori MSVC (qualcosa come 7.0 e versioni successive) collegando in un file oggetto denominato nothrownew.obj. In realtà c'è un serie piuttosto complessa di regole nel 7.0 e 7.1 dei compilatori (VS2002 e VS2003) per determinare se essi insolute alla non-lancio o new lancio.

Sembra che MS pulire questo in su a 8,0 (VS2005) -ora è sempre il valore predefinito è un gettare nuova a meno che non specificatamente collega a nothrownew.obj.

Si noti che è possibile specificare che si desidera new per tornare 0 invece di buttare std::bad_alloc utilizzando il parametro std::nothrow:

SomeType *p = new(std::nothrow) SomeType;

Questo sembra funzionare in VC6, quindi potrebbe essere un modo per più o meno meccanicamente correggere il codice di lavorare lo stesso con tutti i compilatori in modo da non dover rielaborare la gestione degli errori esistente.

Altri suggerimenti

Mi piacerebbe aggiungere il parere (un po 'controverso) che il controllo per NULL dopo un tentativo di allocazione è praticamente un esercizio di futilità. Se il programma viene eseguito sempre in quella situazione, è probabile che non si può fare molto di più di uscire in fretta. E 'molto probabile che qualsiasi successivo tentativo di assegnazione sarà anche fallire.

Senza controllare per NULL, il codice successivo avrebbe tentato di dereference un puntatore NULL, che tende a uscire dal programma veloce, con un relativamente unico (e facilmente debuggable) condizione di uscita.

Non sto cercando di parlare con voi di controllare per NULL, è certamente la programmazione di coscienza. Ma non si guadagna molto da esso, se non in casi molto particolari in cui si può forse memorizzare alcune informazioni di ripristino (senza allocare più memoria), o libero meno importante di memoria, ecc Ma questi casi sarà relativamente raro per la maggior parte delle persone.

Detto questo, avevo appena fido del compilatore di gettare bad_alloc, personalmente -. Almeno nella maggior parte dei casi

In base alla spec C ++, sarà sempre buttare std :: bad_alloc quando si utilizza semplicemente nuovo senza params, ma naturalmente ci possono essere alcuni compilatori non conformi.

Non vorrei il codice per essere compatibile con compilatori non c ++ compatibile però. VC6 essere uno di loro a questo riguardo.

E 'buona norma comunque di impostare sempre il puntatore a NULL quando li cancelli. Quindi, a causa di ciò, il controllo per NULL è ancora necessaria.

Detto questo, qui ci sono un paio di opzioni per ripulire il codice:

Opzione 1: Impostare il proprio nuovo gestore

Un modo sicuro per ripulire il codice sarebbe chiamare: set_new_handler prima.

Poi si potrebbe verificare la presenza di NULL nel gestore e gettare std :: bad_alloc lì se NULL viene restituito.

Se ti piace eccezioni meglio, allora questa è la soluzione migliore. Se vi piace di restituire NULL meglio allora si può anche fare che facendo un fermo all'interno del nuovo gestore.

Opzione 2: uso sovraccaricato nuovo

Il file di intestazione c ++ standard definisce nothrow struct che è vuoto. È possibile utilizzare un oggetto di questa struct all'interno nuova per ottenere la sua versione di overload che restituisce sempre NULL.

void* operator new (size_t size, const std::nothrow_t &);
void* operator new[] (void *v, const std::nothrow_t &nt);

Quindi, nel codice:

 char *p = new(std::nothrow) char[1024];

Ecco una buona refrence per ulteriori letture

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