View Full Version : [C] Gestione errori
Ciao, vorrei sapere se in C esiste qualche tipo di "error handler"....mi spiego, ho sempre sottomano un mega-progamma C davvero casinoso, purtroppo il C non lo conosco a fondo come vorrei,ma mi tocca lo stesso metterci mano.
Ho una structure che ad un certo punto viene popolata con dati errati (non so perchè, ma col debugger del VisualC vedo solo "Error: expression cannot be evaluated") e ovviamente il programma termina in modo anomalo appena il programma tenta di leggerci.
Ho anche fatto una prova banale , leggendo e testando un valore di un campo di questa struttura, per cercare di 'trappare' l'errore (ossia, se il campo è 0, allora la struttura è ok, visto che altrimenti ci sarebbe quel "Error") ma niente da fare, il programma termina anomalo ancora.
Cosa posso fare ?
Grazie
debug passo passo (F10 oppure F11, che sono rispettivamente lo Step Over e lo Step Into) e vedi di preciso qual è l'istruzione che lo fa terminare, che è già un passo avanti. dopodiché cerca di capire perché quell'istruzione lo fa terminare: puntatore nullo? puntatore arbitrario? puntatore a blocco di memoria non più allocato? eccezione? altro?
debug passo passo (F10 oppure F11, che sono rispettivamente lo Step Over e lo Step Into) e vedi di preciso qual è l'istruzione che lo fa terminare, che è già un passo avanti. dopodiché cerca di capire perché quell'istruzione lo fa terminare: puntatore nullo? puntatore arbitrario? puntatore a blocco di memoria non più allocato? eccezione? altro?
E' quel che sto facendo...debug e via, però l'istruzione su cui si ferma, la posso generare anche io, mettendo un semplice test "if (struttura->campo == 0)" quando guardo (sempre col debugger e le finestre di visualizzazione delle variabili) il contenuto di "struttura" , vedo che sono tutti "Error:expression cannot be evaluated" e il problema è che non sempre lo sono...sarà qualche area di memoria che si 'sporca'.
A me servirebbe qualche istruzione che dica al programma "salta questa parte se i valori di struttura sono errati"
banryu79
09-01-2008, 09:21
...quando guardo (sempre col debugger e le finestre di visualizzazione delle variabili) il contenuto di "struttura" , vedo che sono tutti "Error:expression cannot be evaluated" e il problema è che non sempre lo sono...sarà qualche area di memoria che si 'sporca'...
Perdonami, ma non è che quel messaggio (Error:expression cannot be evaluated) il debugger te lo stampa al posto del valore corrente della variabile per il semplice fatto che tu cerchi di fare un "Quick Watch" alla variabile mentre il thread corrente di esecuzione non è ancora entrato nello scope della funzione dove istanzi la struct?
Infatti quel tipo di messaggi nei debugger, in genere, significa che stai, per esempio, interrogando il debugger sul contento di una variabile in un momento in cui essa non è ancora stata istanziata.
Ciao :)
Perdonami, ma non è che quel messaggio (Error:expression cannot be evaluated) il debugger te lo stampa al posto del valore corrente della variabile per il semplice fatto che tu cerchi di fare un "Quick Watch" alla variabile mentre il thread corrente di esecuzione non è ancora entrato nello scope della funzione dove istanzi la struct?
Infatti quel tipo di messaggi nei debugger, in genere, significa che stai, per esempio, interrogando il debugger sul contento di una variabile in un momento in cui essa non è ancora stata istanziata.
Ciao :)
Eh no, l'avevo pensato, ma la variabile in quella istruzione è 'visibile' e cmq quando viene eseguito correttamente, dalla quick watch vedo bene il valore che ha....è che si vede che in qualche area del programma mi si va a coprire questa struttura, o cmq a 'sporcarla' e quando torna in quel punto mi becco l'errore....
banryu79
09-01-2008, 11:56
Ok magari la colpa è di un puntatore che va a scrivere dove non dovrebbe...
Non saprei cosa consigliarti però, così sui due piedi
:)
(non utilizzo più C da 3 anni a questa parte)
E' quel che sto facendo... ok, quindi andiamo al passo successivo: scoprire la causa. se l'istruzione che causa il crash è del tipo "if (struttura->campo == 0)" allora sicuramente "struttura" è un puntatore non valido, o perché contiene NULL, o perché contiene un valore arbitrario, o perché prima puntava ad un'area di memoria che adesso non è più valida (magari è stata deallocata). quale delle tre?
ok, quindi andiamo al passo successivo: scoprire la causa. se l'istruzione che causa il crash è del tipo "if (struttura->campo == 0)" allora sicuramente "struttura" è un puntatore non valido, o perché contiene NULL, o perché contiene un valore arbitrario, o perché prima puntava ad un'area di memoria che adesso non è più valida (magari è stata deallocata). quale delle tre?
Io presumo la terza, la QuickWatch mostra solo "Error:Expression cannot be evaluated" per tutti i campi che compongono la struttura.
In qualche modo, sta struttura viene 'corrotta' e quando faccio il mio test mi causa l'errore.
Ho aggiunto un modulo Try..Catch che ho trovato su internet, ma non funziona come dovrebbe....
Io presumo la terza, la QuickWatch mostra solo "Error:Expression cannot be evaluated" per tutti i campi che compongono la struttura.
In qualche modo, sta struttura viene 'corrotta' e quando faccio il mio test mi causa l'errore.
Ho aggiunto un modulo Try..Catch che ho trovato su internet, ma non funziona come dovrebbe.... che il quick watch mostrasse "Error: expression cannot be evaluated" credo che ormai fosse abbastanza chiaro... quello che mi interessa è il valore numerico del puntatore che nello pseudocodice abbiamo chiamato "struttura". se si tratta della terza (valore arbitrario che era valido prima e ora non più) allora puoi mettere in atto diverse strategie a seconda di com'è fatto il programma; per esempio prova a cercare nei sorgenti tutti i posti in cui utilizzi quel puntatore, nello specifico quelli in cui deallochi la memoria a cui punta.
Rieccomi, dopo un pò di debugging....
Dunque, l'errore si presenta saltuariamente, ossia, magari il programma gira tranquillamente e passa quelle istruzioni senza problemi, io col debug magari lo vedo passarci senza problemi per due o tre volte, poi, senza un motivo, mi ritrovo quell' "Error" nel valore della struttura.
Ho notato che quando gira correttamente, nella struttura ho il valore "0xFeeeFeee", significa che la struttura è stata deallocata ? ho provato a porla a "Null" prima di eseguire una sua rivalorizzazione, ma non c'è niente da fare, se contiene "Error", le istruzioni seguenti mi mandano in crash...
if ((l = (struct link_t*)GetWindowLong(hwnd, GWL_USERDATA)) != NULL)
{
cp = (struct control*)l->item;
dg1p = (struct data_grid1*)cp->cdp;
dove:
static struct link_t *l = NULL;
static struct control *cp = NULL;
static struct data_grid1 *dg1p = NULL;
Non so se vi bastano come info, ma per uno che di C non sa praticamente nulla, è dura spiegarsi...sorry.
AGGIORNAMENTO:
Dunque, ho visto che l'oggetto CP, ossia la struttura che mi genera l'errore, è valorizzata errata a seguito dell'istruzione
if ((l = (struct link_t*)GetWindowLong(hwnd, GWL_USERDATA)) != NULL)
(i suoi campi diventano tutti "Error:...." )
C'è qualche cosa che non va in questa chiamata ?
banryu79
10-01-2008, 11:07
GetWindowLong() dovrebbe restituire un LONG.
Prova a fare la chiamata fuori dall'if e catturare il valore di ritorno e stamparlo.
Se la funzione viene eseguita con successo quel LONG contiene il valore a 32 bit richiesto; se invece fallisce dovrebbe restituire 0
GetWindowLong (http://msdn2.microsoft.com/en-us/library/ms633584.aspx)
GetWindowLong() dovrebbe restituire un LONG.
Prova a fare la chiamata fuori dall'if e catturare il valore di ritorno e stamparlo.
Se la funzione viene eseguita con successo quel LONG contiene il valore a 32 bit richiesto; se invece fallisce dovrebbe restituire 0
GetWindowLong (http://msdn2.microsoft.com/en-us/library/ms633584.aspx)
Seguendolo in debug, vedo che la variabile in cui appoggio il valore di quella GetWindowLong, è sempre uguale, ma dopo l'assegnazione alla struttura " L ", mi ritrovo con la struttura "cp" piena di fuffa...(ma solo dopo un paio di 'giri', la prima volta gira correttamente sempre!)
Non c'è modo di spazzare via completamente cp e quindi valorizzarla da vuota ?
banryu79
10-01-2008, 11:29
Non c'è modo di spazzare via completamente cp e quindi valorizzarla da vuota ?
Dunque, "cp" viene assegnata così:
cp = (struct control*)l->item;
tramite il puntatore "l", il quale a sua volta sarebbe il casting del ritorno di GetWindowLong(), quindi una variabile di tipo LONG, a una di tipo (struct link_t*)
Forse qui succede qualcosa che no va?
Premetto che non sono un esperto, non vorrei portarti su una traccia falsa, ma forse il problema potrebbe essere lì.
E' proprio lì che succede il 'danno' anche secondo me....seguendolo in debug, vedo che appena passa dalla valorizzazione della prima struttura, cp viene riempito di "error".... secondo me è la 'GetWindowLong' che fa casino, ma non so come ovviare all'errore...:muro:
banryu79
10-01-2008, 12:28
secondo me è la 'GetWindowLong' che fa casino, ma non so come ovviare all'errore...:muro:
Secondo me no, non è colpa della GetWindowLong.
Come detto sopra, in ogni caso, ritorna un LONG il cui valore è un valore a 32 bit e rappresenta l'informazione richiesta se la funzione esegue con successo, oppure vale zero se la funzione fallisce.
Quale informazione viene richiesta, in questo caso, lo vediamo nel secondo parametro passato in ingresso (il primo parametro è l'HANDLE alla finestra di cui si richiede l'informazione): GWL_USERDATA.
Guardando su MSDN si legge che:
GWL_USERDATA
Retrieves the user data associated with the window.
This data is intended for use by the application that created the window.
Its value is initially zero.
Quindi possiamo concludere che, se da qualche parte nel codice non viene utilizzata una funzione per settare questo valore a qualcosa di significativo, esso varrà sempre e comunque zero (sia se la funzione viene eseguita con successo sia in caso contrario).
[nel caso te lo stessi chiedendo, la funzione per settare quel valore sarebbe questa: SetWindowLong (http://msdn2.microsoft.com/en-us/library/ms633591(VS.85).aspx), passandogli come secondo parametro "GWL_USERDATA" e come terzo un LONG che è il valore a cui si vuole settare il parametro. Intanto potresti verificare se questa funzione nell'applicazione viene invocata da qualche parte oppure no.]
Penso sarebbe il caso di capire nel dettaglio che strutture siano in coinvolte e cosa succeda di preciso qui:
if ((l = (struct link_t*)GetWindowLong(hwnd, GWL_USERDATA)) != NULL)
[1] Ha senso castare la variabile di tipo LONG tornata dalla funzione alla variabile di tipo (struct link_t*)?
cp = (struct control*)l->item;
[2] Quando, tramite il puntatore a struct link_t "l" si accede al campo "item" la deferenziazione del puntatore cosa produce? E' sempre tutto ok?
[3] ammesso che il punto [2] sia ok, ha poi senso castare la deferenziazione del puntatore l al tipo (struct control*) ?
Questo è quello che io proverei a controllare, magari cambiando il codice in quei due passaggi per fargli compiere una sola operazione per riga ed esaminando in debug i singoli valori prodotti da ogni operazione.
Intanto grazie per tutti i vostri consigli, non sapendo più dove sbattere la testa, sono preziosissimi per me.
Tornando al problema....il Long che mi ritorna dalla GetWindowLong è ok, l'ho messo in una variabile d'appoggio ed è corretto, anche quando il giro va male.
Che sia il casting di "l" ?
Se non ho capito male, la GetWindowLong ritorna un Long che ho settato per la finesta attiva....non c'è modo di usare magari un'altra funzione ? ho visto che c'è la SetWindowLong per settare correttamente GWL_USERDATA, magari è proprio il fatto che non riesce a ricavare info sulla finestra corrente a metterlo in crisi....:muro:
banryu79
10-01-2008, 13:56
Dunque, ragioniamo un attimo:
Se non ho capito male, la GetWindowLong ritorna un Long che ho settato per la finesta attiva...
[omissis]
...ho visto che c'è la SetWindowLong per settare correttamente GWL_USERDATA, magari è proprio il fatto che non riesce a ricavare info sulla finestra corrente a metterlo in crisi....:muro:
Non credo sia quello il problema: se la finestra a cui si fa riferimento nella GetWindowLong (e il primo parametro passato in ingresso, l'HANDLE alla finestra) non fosse valido *credo* che la funzione fallirebbe: nel qual caso tornerebbe comunque un LONG valido, semplicemente di valore zero.
Infatti:
Tornando al problema....il Long che mi ritorna dalla GetWindowLong è ok, l'ho messo in una variabile d'appoggio ed è corretto, anche quando il giro va male.
Infatti, vale zero in quel caso. La variabile restituita è sempre valida.
Il che ci porta a:
Che sia il casting di "l" ?
Io *a naso* penso proprio che il problema abbia a che fare con i casting...
Prova a controllare le definizioni delle strutture a cui si casta (struct link_t e strutc control).
Buona caccia :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.