chiamate nidificate può portare ad argomenti non inizializzate in C?
Domanda
è len
inizializzato correttamente e sicuro in call set_array
?
void object_copy (Object* self, Object* obj) {
int len;
object_set_array (self, object_get_array (obj, &len), len);
}
Se no, cosa mi consiglia?
Soluzione
No - non c'è nessun ordine definito di valutazione per argomenti di una chiamata di funzione.
Anche se la chiamata a object_get_array()
deve avvenire prima della chiamata a object_set_array()
, il valore che il compilatore calcola e passa object_set_array()
per il parametro len
può essere fatto prima che il compilatore effettua la chiamata a object_get_array()
.
Non sono sicuro di quello che il secondo parametro per la chiamata object_set_array()
è destinato ad essere - forse si voleva utilizzare l'operatore virgola:
void object_foo (Object* self, Object* obj) {
int len;
object_set_array (self, (object_get_array (obj, &len), len));
}
Il che avrebbe funzionato, ma è confusa e qualcosa che non lo consiglio.
Credo che quello che vuoi è:
void object_foo (Object* self, Object* obj) {
int len;
object_get_array (obj, &len); // get the length from obj
object_set_array (self, len)); // set the len for self
}
Altri suggerimenti
No. Il terzo parametro di object_set_array()
potrebbe essere valutato e inserito nello stack prima del secondo parametro (object_get_array()
) viene valutato.
Probabilmente si desidera
void object_copy (Object* self, Object* obj) {
int len;
/* I'm just guessing as to the return type */
Object *pObj = object_get_array(obj, &len);
object_set_array (self, pObj, len);
}
Si passa len
dal valore nella chiamata object_set_array()
prima che venga inizializzato. In modo che è sbagliato e un buon compilatore mettere in guardia su questo. La variabile conterrà un valore casuale, in modo che il codice non si bloccherà, ma non farà quello che probabilmente si desidera.
Se object_get_array
fallisce, allora len
potrebbe non ottenere inizializzato. Sarebbe meglio object_get_array
chiamata prima prima di chiamare object_set_array
, in che modo si potrebbe verificare se la chiamata ha funzionato oppure no.
Ecco un esempio di codice, notare che io non so cosa object_get_array
torna così ho usato un void *
per rendere più facile da spiegare:
void *obj; obj = object_get_array(obj, &len); if (obj != NULL) object_set_array(self, obj, len);
Il codice che hai scritto è pericoloso, ma ricorrere a scorciatoie come questo potrebbe portare a pensare che object_set_array
ha fallito e non object_get_array
. Bisogna giudicare voi stessi se non riuscirà o no, ho sempre assumere il codice non riesce in modo che posso mettere in atto misure di salvaguardia, il suo approccio sarà diverso, alcuni tasti di scelta rapida sono ok, questo non è!
Anche se, codice C viene eseguito da sinistra a destra, secondo l'ordine di come l'espressione viene valutata (dipende dal compilatore e codice compilato), se la funzione ha funzionato, allora sì, len
sarebbe inizializzato, ma è non è sicuro.
Spero che questo aiuti, I migliori saluti, Tom.
Questo funzionerà anche:
ARRAY object_get_array (Object* self, int* len);
void object_set_array (Object* self, ARRAY array, const int* len);
// ...
void object_copy (Object* self, Object* obj) {
int len;
object_set_array (self, object_get_array (obj, &len), &len);
}
perché la chiamata a object_get_array()
sarà valutata prima della chiamata a object_set_array()
, a quel punto len
sarà stato impostato il valore corretto.