Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    33

    [C] Riallocazione Array Dinamico

    Ciao a tutti !
    Ho un problema con la funzione di riallocazione di un array dinamico. La funzione che mi riporta il libro la seguente :

    codice:
    void array_resize(TArray *a, int new_length){
       if(new_length> (a->size) || new_length< (a->size-SHRINK_DELTA)){
          int new_size=new_length+GROWING_DELTA;
          a->item=realloc(a->item, new_size*sizeof(TInfo));
          assert(new_size==0 || a->item!=NULL);
          }
       a->length=new_length;
    }
    Ora la assert dovrebbe controllare che le condizioni siano vere, e in quel caso il programma procede correttamente. Per quanto riguarda la condizione "a->item!=NULL" è il banale controllo che assicura la corretta riallocazione; quel che non capisco è perche "new_size" debba essere uguale a 0 ! Considerando anche che GROWING_DELTA è una costante positiva a maggior ragione new_size, per come inizializzata, sarà >0. Dov'è l'errore ?

  2. #2
    È giusto una verifica di una postcondizione della tua funzione; ora come ora è impossibile che ciò accada, ma metti che modifichi il codice e salta fuori un percorso "imprevisto" per cui può essere che new_size risulta uguale a zero, con la assert te ne accorgi immediatamente.

    Per inciso, non è una buona idea usare la realloc in quella maniera. Se non c'è sufficiente memoria, infatti, la realloc può fallire, restituendo NULL, che viene memorizzato in a->item. Il problema è che quando la realloc fallisce non libera il blocco di memoria che le era stato passato, ma ora che hai sovrascritto a->item non hai più possibilità di liberarlo manualmente.
    Finché la reazione alla mancanza di memoria è un assert (che termina il programma) non liberare esplicitamente la memoria non è un grosso problema, ma è sempre bene tenere a mente questa peculiarità della realloc.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    33
    È giusto una verifica di una postcondizione della tua funzione; ora come ora è impossibile che ciò accada, ma metti che modifichi il codice e salta fuori un percorso "imprevisto" per cui può essere che new_size risulta uguale a zero, con la assert te ne accorgi immediatamente.
    Si ma quindi dovrebbe essere !=0 e non ==0 no ? visto che la assert da errore nel caso in cui la condizione è falsa ! e poi perchè controllare solo per 0 e non per -1, -56 ecc ? supponiamo che io prima di chiamare la funzione controllo che sia new_length >0, o al più maggiore di -GROWING_DELTA, in quel caso non avrei più bisogno di questa condizione giusto ?

    Per inciso, non è una buona idea usare la realloc in quella maniera. Se non c'è sufficiente memoria, infatti, la realloc può fallire, restituendo NULL, che viene memorizzato in a->item. Il problema è che quando la realloc fallisce non libera il blocco di memoria che le era stato passato, ma ora che hai sovrascritto a->item non hai più possibilità di liberarlo manualmente.
    Finché la reazione alla mancanza di memoria è un assert (che termina il programma) non liberare esplicitamente la memoria non è un grosso problema, ma è sempre bene tenere a mente questa peculiarità della realloc.
    Quindi mi conviene usare un puntatore "provvisorio" in questo caso ?
    Grazie per la risposta.

  4. #4
    Originariamente inviato da Gauss92
    Si ma quindi dovrebbe essere !=0 e non ==0 no ? visto che la assert da errore nel caso in cui la condizione è falsa !
    Hai ragione, dovrebbe essere
    codice:
    assert(new_size!=0 && a->item!=NULL);
    supponiamo che io prima di chiamare la funzione controllo che sia new_length >0, o al più maggiore di -GROWING_DELTA, in quel caso non avrei più bisogno di questa condizione giusto ?
    Ci sono diverse scuole di pensiero sulla questione, per cui ti direi "ni"
    Logicamente non dovrebbe accadere, ma credo che nello spirito di quel codice sia una verifica di postcondizione che fai indipendentemente da quello che è il codice della funzione. Vedila un po' come un check fatto da un osservatore esterno, che verifica se la funzione ha effettivamente fatto il suo dovere.
    Quindi mi conviene usare un puntatore "provvisorio" in questo caso ?
    Sì; tra l'altro, dato che il fatto che la realloc restituisca NULL è una cosa che può capitare (anche se molto di rado), probabilmente ha più senso verificarla con un normale if (eventualmente restituendo un codice di errore) piuttosto che con un assert, che viene rimosso nel momento in cui compili in modalità release.
    In altri termini, l'idea dell'assert è verificare errori logici nel tuo programma (nel qual caso ha senso terminare il programma, finché lo stai ancora sviluppando), mentre, se hai errori di runtime che non dipendono strettamente da te (tra cui ad esempio l'esaurimento della memoria), la cosa più sensata è riportare in qualche modo il problema al chiamante, per il quale magari il problema non è così grave da mandare in crash il programma.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    33
    Ok grazie mille

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.