Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    C free(...) Exception: STATUS_ACCESS_VIOLATION

    Salve ragazzi, rieccomi qui, con un nuovo quesito, e nella speranza di un vostro aiuto che come sempre è stato eccezionale.
    Ho provato gia a cercare risposta ai miei quesiti QUI ma non mi è stato di aiuto.
    La funzione che sto per postarvi, almeno dalle prove che ho fatto fa il suo dovere.
    Quello che fa è confrontare tutti gli elementi della lista A con tutti gli elementi della lista B. In particolare vengono confrontati i membri "val".
    -Se A->val == B->val, la funzione accoda la stringa di quell'elemento di B alla stringa dell'elemento di A.
    -Se invece A->val è diverso da tutti quelli di B allora l'elemento in quel momento puntato da A va eliminato dalla lista.
    Un esempio è questo:
    A = {2, "Tara"} -> {1, "Pietra"} -> {2, "Casa"} -> {1, "Gioco"} -> {4, "Albero"}
    B = {5, "Mela"} -> {1, "Mulo"} -> {4, "Campo"} -> {1, "Erba"}

    allora la funzione modifica la lista A così:

    {1, "PietraMuloErba"} -> {1, "GiocoMuloErba"} -> {4, "AlberoCampo"}
    Ok, detto questo, il probelma della mia funzione è che il free della riga 25 mi genera errore. Se invece non faccio quel free(e quindi non elimino dalla memoria quell'elemento) la funzione funziona... Potete svelarmi il mistero??

    Struttura di riferimento:
    codice:
    typedef struct Elem {
    	long		 val;
    	char*		 str;
    	struct Elem *next;
    } Elem, *List;
    Funzione:
    codice:
    List join(List A, List B) {
    	List Acpy = A, libera = NULL, prec = NULL;
    	List Bcpy = B;
    	int boolEl;
    	
    	while(A != NULL) {
    		libera = A;
    		boolEl = 1;
    		B = Bcpy;
    		while(B != NULL) {
    			if(A->val == B->val) {
    				strcat(A->str, B->str);
    				boolEl = 0;
    			}
    			B = B->next;
    		}
    		if(!prec && boolEl) {
    			A = A->next;
    			free(libera);
    			Acpy = A;
    		}
    		else if(prec && boolEl) {
    			A = A->next;
    			prec->next = A;
    			free(libera);                         <----E' LUI L'IMPUTATO
    		}
    		else if(!boolEl) {
    			prec = A;
    			A = A->next;
    		}
    	}
    	return Acpy;
    }
    Errore:
    Exception: STATUS_ACCESS_VIOLATION at eip=6110D359
    eax=ADBD9314 ebx=7245D0CC ecx=0E48ADED edx=20030280 esi=200363E0 edi=ADBD9314
    ebp=0022CC98 esp=0022CBF0 program=C:\cygwin\home\3\a.exe, pid 3792, thread main
    cs=001B ds=0023 es=0023 fs=003B gs=0000 ss=0023
    Stack trace:
    Frame Function Args
    0022CC98 6110D359 (200302A8, 00000000, 0022CCE8, 49435341)
    0022CCC8 004011E0 (00000001, 0022CCF0, 20010100, 612671DE)
    0022CD58 61006EE8 (00000000, 0022CDA8, 610064E0, 00000000)
    End of stack trace
    Segmentation fault (core dumped)
    Vi ringrazio

  2. #2
    oddio non ditemi che strcat non allunga la stringa di destinazione... faccio subito delle prove ed alloca memoria per loro

  3. #3
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    No che non allunga ...

    *Lo spazio per le stringhe in C deve essere allocato dal programma prima di utilizzarlo*

    Non mi sembra una regola difficile ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  4. #4
    Allora alla luce del fatto che strlen ritorna la lunghezza della stringa senza contare il carattere nullo di terminazione, ho aggiunto questa riga ed adesso non c'è piu l'errore.
    Vorrei però una conferma da te sul fatto che ho fatto bene a non aggiungere in +1
    codice:
    A->str = realloc(A->str, sizeof(char)*(strlen(B->str)+strlen(A->str)));

  5. #5
    Mi sa che quest'ora sono un po fuso, ho rifatto i conti, SONO SICURO che DEVO mettercelo il +1 ma non capisco perche funziona anche se non lo metto o addirittura ci metto -1
    Come mai????????????

  6. #6
    No, il +1 lo devi mettere: le due strlen ti dicono solo il numero dei caratteri "veri" che la tua stringa finale avrà, ma tu ne devi mettere in conto uno in più appunto per il null finale.
    ---EDIT---
    Appunto. Funziona "per caso" - probabilmente la realloc ti ha fornito un po' più di memoria (capita, a seconda di come è la situazione nell'heap), o, più probabilmente, il posto che sei andata ad occupare "abusivamente" appartiene all'heap ma non è ancora in uso, per cui non hai ripercussioni particolari.
    Tieni presente che i bug di questo genere sono tra i più pericolosi, proprio perché spesso non hai nessuna indicazione della loro presenza, ma "ogni tanto" ottieni dei comportamenti imprevisti.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Certo che lo devi aggiungere ... se funziona, come ti ho detto altre volte, è solo per caso, finché non danneggi il contenuto di altre variabili o addirittura vai a finire in una zona di memoria non allocata al processo.
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  8. #8
    Ok ti ringrazio
    Ora succede una cosa strana, il programma non mi da l'errore se non ci metto +1 e addirittura funziona ance se ci metto -1. Se metto -2 schiatta. Come mai fino a -1 funziona??????

  9. #9
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Leggi la mia ultima risposta ...

    Non conta il -1 o il -2 ... dipende da che zona di memoria "sporchi" ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  10. #10
    Ahh ho capito adesso. Scusa se spesso sono ripetitivo è che magari non mi viene in mente la risposta al quesito...
    Sei davvero gentile oregon, come sempre. Grazie ancora
    Grazie anche a MItaly gentilissimo.

    tanto per fisssare il concetto xD
    codice:
    P    I    E    T    R    A    \0
                                      M    U    L    O    \0
                                      1     2    3    4         <-- strlen di mulo ritorna 4
    1    2    3    4    5    6                                 <--strlen di pietra torna 6
                                                                    aggiungo 1 per il carattere terminatore
    Buonanotte ragazzi!

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 © 2025 vBulletin Solutions, Inc. All rights reserved.