Newsgroup: it.comp.programmare
Titolo: Problema di memoria?

Salve!
Ho un problema con un programma scritto da me in C.
In breve il problema è questo: il mio programma (utilizzando una delle
funzioni fornite dall'SDK di un sensore per il rilevamento i impronte
digitali) deve confrontare tra di loro di svariate coppie di immagini e
restituire il punteggio di somiglianza delle due impronte salvando i
risultati su un file txt.
Il problema è che quando dico "svariate coppie di immagini", in realtà
intendo dire che i confronti che il programma deve fare sono 1428000 (ebbene
sì, quasi un milione e mezzo).
Ovviamente (almeno credo che sia ovvio), il mio programma dopo circa 500
confronti esce e torna al prompt (senza nessun messaggio di errore) oppure
addirittura fa flippare il computer.
Ho pensato di scomporre tutti i cicli for che generano le coppie da
confrontare in modo da avere ogni volta un numero pari a 500 confronti ma
dovrei effettuare questa modifca 2856 volte, e ogni volta rilanciare il
programma modificando i parametri (in pratica dovrei fare a mano il ciclo
for incrementando ogni volta a mano il contatore)... direi che la cosa non è
fattibile.
Qualcuno sa suggerirmi un modo per affrontare la questione?
Grazie mille
-- 
Elminster 

 addirittura fa flippare il computer.
Non mi sembra tanto ovvio...se non c'è nessuna istruzione di uscita
condizionale nel tuo programma, deve essere un bug dell'sdk che usi...ti
conviene debuggare il tuo codice prima, poi vedi sul sito del produtore
del sensore se è presente qualche aggiornamento o segnalazione di bug, o
meglio ancora vedi nella documentazione se c'è qualche nota! così è un
po'difficile darti risposte!

 qualche nota! così è un po'difficile darti risposte!
Son sicuro che non ci siano bug... il programma funziona egregiamente se 
invece di lanciare un ciclo che va da 1 a 10mila lo lancio 20 volte ogni 
volta impostando il ciclo da 1 a 500, da 501 a 1000, da 1001 a 1500, ecc.
Il problema avviene quando l'esecuzione diventa troppo "pesante"... capisci?
Per questo mi rivolgo a voi che di sicuro siete più esperti di me in 
programmazione. Se create un programma che effettua un'operazione abbastanza 
onerosa in termini di memoria (che so, potrebbe essere un task di 
elaborazione di video o qualcosa di simile) e questa operazione la effettua 
per un milione di volte di seguito, non è normale che a un certo punto il 
programma esca perchè "non ce la fa più"? ;-)
Ripeto: parlo da inesperto, però mi sembrava abbastanza plausibile 
ipotizzare che il programma si interrompesse per mancanza di memoria. Per 
questo vi chiedevo se esisteva un modo per aggirare questo problema.
Attendo vostri pareri
Grazie mille (il programma mi serve per un progetto universitario quindi è 
abbastanza importante)
-- 
Elminster 

 punto il programma esca perchè "non ce la fa più"? ;-)
Utilizzi l'allocazione statica o l'allocazione dinamica? 
Sotto che piattaforma lavori?
Potresti postare il frammento di codice incriminato?
-- 
[ Andrea Spadaccini - a.k.a. Lupino/Lupin85 - Catania - ICQ#: 91528290 ]
[ GPG ID: 5D41ABF0 - key @ 
pgp.mit.edu
 - Slackware 10.1 w/Linux 2.4.22 ]
[ Linux User # 313388 - MAIL: a.spadaccini(at)catania(dot)linux(dot)it ]
[ Pseudo-random numbers made me listen to: James Blunt - So Long Jimmy ]

 Potresti postare il frammento di codice incriminato?
Windows XP.
In realtà io le immagini non le carico in memoria.
Ecco il codice che uso:
stream = fopen("ms.txt", "w");
differenza= fopen("diff.txt", "w");
    for (i=1; i<=6; i++) {
     for (k1=1; k1<=10; k1++){
      for (k2=k1; k2<=10; k2++) {
       if (k1!=k2) {
        s1 = creanome("C:", i, k1, j);
        s2 = creanome("C:", i, k2, j);
        f1 =  verifica(s1,s2);
        f2 =  verifica(s2,s1);
        fprintf(stream, "%f\n", f1);
        fprintf(stream, "%f\n", f2);
        fprintf(differenza, "%f\n", fabs(f1-f2));
        }
       }
      }
     }
    }
      fclose(stream);
        fclose(differenza);
}
Questo è il ciclo che effettua 10800 confronti, poi ne ho un altro che ne
effettua un milione e mezzo.
La funzione creanome è una semplice funzione che a partire da 4 parametri
(percorso e 3 contatori), restituisce una stringa così fatta
<percorso>//i-k-j.tif
Verifica è la funzione che non fa altro che confrontare le due immagini e 
restituire un float che è uguale al
"matching score" delle due impronte.
Bene, sia usando questo ciclo che usando quello più esteso, dopo circa 500
ripetizioni il programma si impalla.
La funzione verifica è la seguente (ho tolto tutte le dichiarazione di 
variabili). L'unica parte che ho aggiunto io riguarda la conversione del 
primo parametro da tif a modello. Potrebbe essere lì l'errore? In quel 
malloc che ho usato? L'ho dovuto fare per forza perchè originariamente la 
funzione della SDK accettava in ingresso solo un modello come primo 
parametro e un'immagine come secondo parametro mentre a me serviva che 
potesse accettare due immagini.
Tenete comunque conto che quando lanciata per "sole" 500 volte la funzione 
lavora benissimo e fa esattamente quello che deve fare.
float verifica(char *mod, char *f)
{
//se il primo parametro è un file tif
if (strstr(model,".tif"))
 {
 err=FX3_LoadFingerprintFromFile(model,&quality);
 if (err) {printf("\nErrore di caricamento impronta");FX3_End();return 1;}
  else printf("\nImpronta acquisita.");
 err=FX3_CreateModel();
 modelp = (BYTE*)malloc(20000);// getchar();
 err=FX3_SaveModelToMemory(modelp, 0, num, dimension);
 if (err) {printf("\nErrore di conversione impronta %s 
errore:%d",model,err); return 1;}
  else  printf("\nImpronta %s convertita in modello",model);
 err=FX3_LoadModelFromMemory(modelp);
 if (err) {printf("\nErrore di caricamento modello %s errore:%d",model,err); 
return 1;}
  else  printf("\nModello %s caricato",model);
 free(modelp);
 }
//se il primo parametro è un file .mdl
else {err=FX3_LoadModelFromFile(model);
 if (err) {printf("\nErrore di caricamento modello %s errore:%d",model,err); 
return 1;}
  else  printf("\nModello %s caricato",model);
  }
//se il secondo parametro è un modello
if (strstr(fingerprint,".mdl"))
 {
 err=FX3_LoadFingerprintFromModelOnFile(fingerprint);
 if (err) {printf("\nL'impronta %s non puo' essere caricata dal modello, 
Errore:%d",fingerprint,err);FX3_End();return 1;}
   else printf ("\nInpronta %s acquisita",fingerprint);
 }
else //matching impronta con modello
 {
 err=FX3_LoadFingerprintFromFile(fingerprint,&quality);
 if (err) {printf("\nErrore di caricamento impronta %s, 
Errore:%d",fingerprint,err);FX3_End();return 1;}
  else printf("\nImpronta %s acquisita.",fingerprint);
 }
//matching
err=FX3_Matching(1.0,&similarity);
if (err) {printf("\nMatching error, Errore:%d",err);FX3_End();
 return 1;}
else printf("\n\nSimilarita' matching:%5.4f\n",similarity);
return similarity;
}}
-- 
Elminster 

Lancia l'applicazione e verifica tramite task manager l'utilizzo di
memoria da parte del tuo processo.
è probabile che nei cicli da te implementati tu allochi continuamente
nuova memoria, anzichè allocarla una solo volta fuori dal ciclo for.
ciao 
lorenzo

  modelp = (BYTE*)malloc(20000);// getchar();
Ho notato che ci sono dei return prima della free().. 
IMHO dovresti fare la free() prima di ogni return, altrimenti la memoria
allocata resta inutilizzabile.
Non ho visto altri potenziali bug, sinceramente.
-- 
[ Andrea Spadaccini - a.k.a. Lupino/Lupin85 - Catania - ICQ#: 91528290 ]
[ GPG ID: 5D41ABF0 - key @ 
pgp.mit.edu
 - Slackware 10.1 w/Linux 2.4.22 ]
[ Linux User # 313388 - MAIL: a.spadaccini(at)catania(dot)linux(dot)it ]
[ Are you curious? I know you are... I'm listening to: Radiohead - You ]


Ho provato a monitorare le risorse occupate tramite Task Manager ma ho
visto che ovviamente l'uso della CPU durante l'esecuzione va al 99-100% ma
comunque il programma non occupa mai più di 3500KB.
Eppure dopo circa 500 cicli il programma torna al prompt senza dire nulla 
(se
lo lancio in Modalità Provvisoria di Windows) o da errore irreversibile (se
lo lancio normalmente).
Non so più come fare... :-(
-- 
Elminster 

 Non ho visto altri potenziali bug, sinceramente.
:-((((
Io non so più come fare... e purtroppo mi serve per l'università!!!
-- 
Elminster 

 Qualcuno sa suggerirmi un modo per affrontare la questione?
Usa un debugger.
Kiuhnm

  err=FX3_LoadFingerprintFromFile(fingerprint,&quality);
Sicuro che a queste FX3_LoadFingerprint non corrispondano delle 
FX3_Free, FX3_Dealloc o qualcosa del genere, per liberare la memoria 
allocata?

 allocata?
Sicuro: tutto viene gestito dalle funzioni FX3_Init e FX3_Close che vengono 
lanciate all'inizio e alla fine di ogni confronto.
-- 
Elminster 

 Io non so più come fare... e purtroppo mi serve per l'università!!!
A questo punto l'unico consiglio valido è quello di Kiuhnm: utilizza un
buon debugger. O, in mancanza di quello, utilizza delle printf() per
localizzare l'errore.
L'errore potrebbe anche essere dovuto ad un utilizzo scorretto delle API
del SDK che hai a disposizione.
Mi dispiace non poterti aiutare ulteriormente.. Sono universitario anche
io e ti capisco! :)




Errore irreversibile in genere è un errore di allocazione di memoria.
vedi bene in questo senso. dereferenzi puntatori null, oppure su cui hai
usato free()?

 funzione nella main che ora appare così (s1 e s2 sono due char*):
non dovrebbe essere la funzione creanome a farsi carico della
deallocazione della memoria.
Cioè tu chiami creanome dal main o da un altra funzione con chiamate
del tipo
char *newname = creanome(...);
quindi compete al chiamante liberare la memoria, verifica se la
creanome viene chiamata più volte durante il loop senza che venga
chiamata la relativa free.
considera che allocare 51 byte per 1 milione di volte ti porta a
51*1000000/1024/1024 = 48 MB circa di memoria.
Perchè non consideri l'idea di spostare la gestione della memoria
fuori dalla tua funzione? cioè evita di allocare e lascia solo la
creazione del nome, passi dall'esterno la variabile con la memoria già
allocata, in questo modo la logica dell'allocazione e deallocazione
vengono mantenute allo stesso livello, con indubbi vantaggi nella
gestione e lettura del codice.
ciao 
Lorenzo


Per quanto ne so, io toglierei le chiamate alle FX3 e a tutto quello
che non appartiene al tuo codice. Sostituirle con delle chiamate False
e fai girare il programma. In questo modo sai se il problema
appartiene realmente al tuo codice.
Ho fatto cicli di 520.000 con accesso a db e files vari senza mai
riscontrare nessun problema, con xp, 2000 e w98.
Dubito fortemente che sia un problema di memoria, xp ti manderebbe prima
su swap file, vedresti, in altre parole, lavorare come un pazzo il
disco rigido, inoltre da task manager vedresti crollare la memoria
degli altri processi, nonchè diventare spaventosamente lento
tutto il sistema, anche dopo che il programma è deceduto.
Rimango dell'ipotesi che qualcosa in quell'sdk .. abbia problemi.
Non programmo molto in c ma mi pare che all'alloc ci sia qualcosa
di alternativo come la globalalloc o qualcosa del genere .. che sei
sicuro che non allochi nell'heap.
Ma di questo non ci metterei la mano sul fuoco.
Infine, l'errore preciso che riporta xp sarebbe ? hai compilato
per win32 ?
	Saluti
	Lorenzo

 }
-- 
/* Costantino Grana                                */
main(int c,char**o){char*s=c?"+L7?+;:7?+:OKIK+9?;9=;"
":+9?;:<:;+9?;;;:;+9<:;<::;+RLJ;K9+":1[o],t,a=!c,m;do
for (m=*s-'0',t=a?m/c:m%c;m>>7?c=1<<m+8,!a&&puts(&a)*
*&a:t--;printf("  \0/*"+a));while ((a^=3)||a[++s]);;}
/* Original code due to Chris Brown... impressive! */

 Ho un problema con un programma scritto da me in C.
Ragazzi, grazie a tutti... sono riuscito a risolvere il problema!!! :-)))
Praticamente l'errore era dovuto al fatto che ogni volta il ciclo rilanciava 
le due funzioni dell'SDK Init() e End().
Queste due funzioni evidentemente non fuzionavano correttamente e creavano 
dei memory leak (anche se in realtà il manuale stesso dell'SDK diceva che 
prima di ogni confronto doveva essere lanciata la Init e subito dopo la 
End).
In realtà però facendo così il programma dopo un po' si flippava: è bastato 
inserire la Init all'inizio della main e la End alla fine per risolvere 
tutti i problemi.
Grazie di cuore comunque a tutti per l'aiuto che mi avete dato (e per la 
vostra pazienza)! ;-)
-- 
Elminster