Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Se fallisce, new restituisce sempre NULL?
Forum - C/C++ - Se fallisce, new restituisce sempre NULL?

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
AldoBaldo (Member)
Expert


Messaggi: 347
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 8:09
Martedì, 29/09/2015
Buongiorno.

Oggi vi secco con una domanda che nasce dai dubbi improvvisi d'una persona che pratica una materia da autodidatta della domenica, senza avere solide basi teoriche. Se scrivo sciocchezze o banalità siate pazienti.

Per anni ho scritto cose tipo:

Codice sorgente - presumibilmente C/C++

  1. CLASSE_X *ptr = new CLASSE_X;
  2. if( ptr == NULL ) return kCodiceErrore;



Qualche tempo fa m'è capitato di leggere, non ricordo dove, che se new fallisce non necessariamente ptr riceve NULL. Garb! Da quel momento ho iniziato a scrivere cose di questo tipo:

Codice sorgente - presumibilmente C/C++

  1. CLASSE_X *ptr = NULL;
  2.  
  3. try {
  4.     ptr = new CLASSE_X;
  5. } catch( ... ) {
  6.     return kCodiceErrore;
  7. }



Ora mi prende una specie di paranoia per cui tentenno tra le due soluzioni senza riuscire a decidere una volta per tutte quale sia quella da usare. Quale delle due versioni è corretta? Se una delle due è corretta e l'altra sbagliata non ci sono se, nè ma: si usa quella corretta e basta. Ammesso che siano corrette entrambe, quale è preferibile? Si incorre in qualche rischio usando la versione sconsigliabile?

Preciso che non mi riferisco ai casi in cui CLASSE_X lancia eccezioni per errori verificatisi nella funzione creatrice, bensì ai casi in cui è proprio l'operatore new che non riesce a portare a termine il proprio compito d'allocazione (magari perché non c'è memoria sufficiente per allocare lo spazio necessario; tipo, se faccio "new int;" non c'è possibilità che fallisca alcuna funzione costruttrice, ma potrebbe non esserci spazio in memoria per allocare l'int in sè e per sè). Spero di essere riuscito a spiegarmi.


Ma cosa vuoi che ne sappia? Io ci gioco, col codice, mica ci lavoro!
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 5475
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 9:46
Martedì, 29/09/2015
Lo standard C++ prevede che sia lanciata una eccezione

std::bad_alloc

se la new fallisce (anche per mancanza di memoria).

Alcune versioni di vecchi compilatori non seguivano questo standard e restituivano NULL.
Ovviamente i moderni compilatori seguono lo standard.

Ultima modifica effettuata da nessuno il 29/09/2015 alle 9:47


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1459
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 14:27
Martedì, 29/09/2015
....a meno che tu non abbia compilato (o scaricato) un compilatore con la libreria standard compilata in modo tale da non lanciare eccezioni.....

PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 347
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 16:08
Martedì, 29/09/2015
Innanzi tutto grazie per avermi riservato la vostra attenzione. Detto questo...

Uso sempre l'IDE Code::Blocks. Nelle impostazioni del compilatore compare "GNU GCC compiler", mentre il log di compilazione riporta, in testa alla compilazione d'ogni modulo, "mingw32-g++.exe". Non sapendo se si tratta di un compilatore moderno o di uno vetusto, dopo aver cercato "std::bad_alloc" col solito Google ho provato a mettere insieme un programmino di test.

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <new>
  3.  
  4.  
  5. int main() {
  6.     const size_t dimBlocco = 1048576; // 1 MB
  7.     const int maxBlocchi = 4096;
  8.     char *ptr = NULL;
  9.     int i;
  10.  
  11.     printf( "Inizio allocazioni\n\n" );
  12.  
  13.     for( i=0; i<maxBlocchi; ++i ) {
  14.         try {
  15.             ptr = new char[dimBlocco];
  16.             if( ptr == NULL ) {
  17.                 printf( "    Allocazione n. %d, puntatore NULL.\n\n", i+1 );
  18.                 break;
  19.             }
  20.         } catch( std::bad_alloc& err ) {
  21.             printf( "    Allocazione n. %d, eccezione.\n", i+1 );
  22.             printf( "    Indirizzo puntato: 0x%08lX\n\n", (unsigned long) ptr );
  23.             break;
  24.         }
  25.     }
  26.  
  27.     printf( "Fine allocazioni\n\n" );
  28.  
  29.     getchar();
  30.     return 0;
  31. }



Il programma, eseguito su un netbook con 2GB di ram, mi dà in output questa roba qui:

Codice sorgente - presumibilmente Plain Text

  1. Inizio allocazioni
  2.  
  3.     Allocazione n. 1916, eccezione.
  4.     Indirizzo puntato: 0x7FE50020
  5.  
  6. Fine allocazioni



...dal che deduco che il compilatore che uso sia di quelli "moderni" e con una libreria strutturata secondo lo standard, perché tentando di allocare il 1916esimo megabyte di memoria "new" lancia l'eccezione "std::bad_alloc", come scriveva nessuno. Deduco anche che la formulazione corretta per usare "new" sia la seconda, cioè...

Codice sorgente - presumibilmente C/C++

  1. CLASSE_X *ptr = NULL;
  2.      
  3. try {
  4.     ptr = new CLASSE_X;
  5. } catch( ... ) {
  6.     return kCodiceErrore;
  7. }



...dove oltre ad acchiappare "std::bad_alloc" acchiappo anche qualsiasi altro tipo d'eccezione dovesse venirgli in mente di lanciare.

Ah! La meravigliosa sensazione di poter scegliere a ragion veduta. :D Grazie ancora, farò tesoro.


Ma cosa vuoi che ne sappia? Io ci gioco, col codice, mica ci lavoro!
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 5475
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 16:18
Martedì, 29/09/2015
Tutto ok ... solo una nota ... il fatto che il compilatore sia o meno recente dipende dalla sua versione, che non ci hai dato ...


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 347
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 17:08
Martedì, 29/09/2015
Eh, che questione che mi poni! Cercando nella cartella di Code::Blocks=>MinGw ho trovato solo questa intestazione, in un file chiamato "README-gcc-tdm.txt":

Codice sorgente - presumibilmente Delphi

  1. === TDM-GCC Compiler Suite for Windows ===
  2. ---        GCC 4.6 & 4.7 Series        ---
  3. ***   Standard MinGW 32-bit Edition    ***
  4.  
  5.  
  6. This edition of TDM-GCC is an unofficial replacement for the official GCC
  7. binaries distributed by the MinGW project; please note the following caveats:
  8.  * TDM-GCC is not formally affiliated with or endorsed by the MinGW project.
  9.  * No level of support for TDM-GCC is in any way guaranteed, although a best
  10.      effort is made to fix bugs as they are found or forward them to GCC
  11.      Bugzilla.



Ma cosa vuoi che ne sappia? Io ci gioco, col codice, mica ci lavoro!
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1459
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 17:13
Martedì, 29/09/2015
da terminale: "mingw32-g++.exe -v "e scopri subito la versione del compilatore.

PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 347
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 17:27
Martedì, 29/09/2015
A che terminale ti riferisci? Alla console del DOS? Non ricordo come si fa a lanciarla, e comunque non ho trovato il file mingw32-g++.exe da nessuna parte sull'hard disk, quindi non saprei quale può essere il percorso... boh?

Edit: il file exe l'ho poi trovato - mingw32-gcc-4.7.1.exe

Ultima modifica effettuata da AldoBaldo il 29/09/2015 alle 17:35


Ma cosa vuoi che ne sappia? Io ci gioco, col codice, mica ci lavoro!
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1459
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 19:03
Martedì, 29/09/2015
chiamasi prompt dei comandi, si accede con tasto windos + R, scrivi cmd.exe e dai invio.
Fai "cd cartella/dell/eseguibile/" e poi "mingw32-gcc-4.7.1.exe -v" ti dice la versione.

PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo