Newsgroup: it.comp.programmare.win32
Titolo: Problemino utilizzo classe TFileStream

Salve a tutti, tempo fa ho scritto un codice per il salvataggio di
immaggini tramite una fotocamera, grazie all'aiuto del NG:
ULONG* F;          // è il puntatore alla grandezza del buffer G
void* G;               // è un puntatore al buffer dove viene allocata
l'immagine
TFileStream *FS ;
for (i=0;i<4;i++)
      {
      ......
      FS = new TFileStream(NIC,fmCreate);
      FS->Write(G, *F);
      free(G);
      }
delete FS;
Prima dichiaro il puntatore FS, l'inizializzo all'interno del ciclo
for, scrive l'immagine contenuta in NIC, una volta scritte 4 immagini,
esce dal ciclo ed elimino il puntatore FS.
I problemi riscontrati sono due: finchè non termino il programma, la
maggior parte dei file non sono apribili in quanto mi dice che i file
sono utilizzati da un altro programma. In pratica non chiude il
collegamento al file; secondo, la memoria non viene liberata, ma le
immagini rimangono in memoria e dopo aver salvato 80-100 immagini si
blocca per memoria satura.

 secondo, la memoria non viene liberata, ma le
Quale memoria? Quella puntata da FS o da G?
HTH,
-- 
Stefano Frosio
www.esse-effe.com

Quale memoria? Quella puntata da FS o da G?
Secondo me in memoria rimane FS, con free(G), dovrei deallocare G
Questa è la funzione per intero:
(Il programma visualizza delle immagini su un secondo form
visualizzato sul proiettore che fa da secondo schermo e poi la
fotocamera acquisisce l'immagine proiettata. sleep, mi serve per dare
il tempo al proiettore di creare l'immagine. La fotocamera è una PL-
A776, una camera firewire industiale, che utilizza librerie
proprietarie.)
void __fastcall TForm1::Button3Click(TObject *Sender)
{
   int i;
   AnsiString NIP="";
   AnsiString NIC="";
   AnsiString strNIma;
   int iNIma;
   AnsiString asCartella="";
   Graphics::TBitmap *ImaLoad[4];
   if ((Trim(edtSourceFile1->Text) == ""))               //Verifica
che sia stato selezionato il file
      {
      MessageBox(NULL, "Inserire la cartella\n dove salvare le
immagini!", "Attenzione", NULL);  //Messaggio di errore se non si
seleziona niente
      return;
      }
   else
      {
      asCartella = edtSourceFile1->Text;             //Cattura la
cartella dove salvare le immagini
      }
   for (i=0;i<4;i++)
      {
      ImaLoad[i]= new Graphics::TBitmap();
      }
   for (i=0;i<4;i++)                                           //
Ciclo per la scansione di tutte le immagini
      {
      NIP="";
      switch (i)
         {
         case 0:
            NIP = "Pattern\\calib0.bmp";
            break;
         case 1:
            NIP = "Pattern\\calib1.bmp";
            break;
         case 2:
            NIP = "Pattern\\calib3_32.bmp";
            break;
         case 3:
            NIP = "Pattern\\calib4_32.bmp";
         }
      ImaLoad[i]->LoadFromFile(NIP.c_str());
      }
   iNIma = StrToInt(Edit1->Text);
   strNIma = Edit1->Text;
   U32 nCam;
   HANDLE phCam1;
   CAMERA_INFO e;
   //PCAMERA_FEATURES pFeatureCam1=NULL;
   //U32 BufferSize;
   PU32 A=NULL;
   PU32 B=NULL;
   float FrameSize;
   float* C;
   int formatIma;
   LPVOID D;
   PFRAME_DESC E;
   PU32 F=NULL;
   LPVOID G;
   long codeReturn;
   AnsiString Str1= "D:\\BCPP\\calib.bmp";
   TFileStream *FS ;
   codeReturn = PxLGetNumberCameras(NULL, &nCam);		// Conta le camere
connesse al sistema, b numero di camere
   if(codeReturn != ApiSuccess)
      {
      MessageBox(NULL, "APIError", "Attenzione", NULL);
      goto END;
      }
   if (nCam<1)
      {
      MessageBox(NULL, "Nessuna camera connessa", "Attenzione", NULL);
      goto END;
      }
   codeReturn=PxLInitialize(0, &phCam1);   // Acquisisce il puntatore
alla camera o i puntatori (
   codeReturn=PxLSetStreamState(phCam1,START_STREAM); // Avvia lo
stream
   // Inserire controllo sull'apertura stream
   // FEATURE_ROI
   A=(PU32)malloc(sizeof(float));
   B=(PU32)malloc(sizeof(float));
   codeReturn = PxLGetFeature(phCam1, FEATURE_ROI, A, B, NULL);
   C=(float*)malloc(*B * sizeof(float));
   codeReturn = PxLGetFeature(phCam1, FEATURE_ROI, A, B, C);
   FrameSize=C[2]*C[3];
   // FEATURE_DECIMATION
   codeReturn = PxLGetFeature(phCam1, FEATURE_DECIMATION, A, B, NULL);
   C=(float*)malloc(*B * sizeof(float));
   codeReturn = PxLGetFeature(phCam1, FEATURE_DECIMATION, A, B, C);
   // FEATURE_PIXEL_FORMAT
   codeReturn = PxLGetFeature(phCam1, FEATURE_PIXEL_FORMAT, A, B,
NULL);
   C=(float*)malloc(*B * sizeof(float));
   codeReturn = PxLGetFeature(phCam1, FEATURE_PIXEL_FORMAT, A, B, C);
   formatIma = (int)C[0];
   switch (formatIma)
   {
      case 0:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_MONO8));
         break;
      case 1:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_MONO16));
         break;
      case 2:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_YUV422));
         break;
      case 3:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_BAYER8_RGGB));
         break;
      case 4:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_BAYER8_GRBG));
         break;
      case 5:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_BAYER8_GBRG));
         break;
      case 6:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_BAYER8_BGGR));
         break;
      case 7:
 
D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_BAYER16_RGGB));
         break;
      case 8:
 
D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_BAYER16_GRBG));
         break;
      case 9:
 
D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_BAYER16_GBRG));
         break;
      case 10:
 
D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_BAYER16_BGGR));
         break;
      case 11:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_RGB24));
         break;
      case 12:
         D=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_RGB48));
   }
   for (i=0;i<4;i++)                                           //
Ciclo per la scansione di tutte le immagini
      {
      NIC="";
      switch (i)
         {
         case 0:
            NIC.Insert(asCartella, asCartella.Length());
            if (iNIma<10)
               NIC.cat_printf("im0%d.bmp",iNIma);
            else
               NIC.cat_printf("im%d.bmp",iNIma);
            break;
         case 1:
            NIC.Insert(asCartella, asCartella.Length());
            if (iNIma<10)
               NIC.cat_printf("im0%dr.bmp",iNIma);
            else
               NIC.cat_printf("im%dr.bmp",iNIma);
            break;
         case 2:
            NIC.Insert(asCartella, asCartella.Length());
            if (iNIma<10)
               NIC.cat_printf("im0%dp.bmp",iNIma);
            else
               NIC.cat_printf("im%dp.bmp",iNIma);
            break;
         case 3:
            NIC.Insert(asCartella, asCartella.Length());
            if (iNIma<10)
               NIC.cat_printf("im0%dn.bmp",iNIma);
            else
               NIC.cat_printf("im%dn.bmp",iNIma);
         }
      Form2->Canvas->Brush->Bitmap = ImaLoad[i];                   //
Assegna l'immagine al form
      Form2->Canvas->FillRect(Rect(0,0,20000,20000));           //
Dimensiona l'immagine
      Form2->Canvas->Brush->Bitmap = NULL;
      Sleep(500);
      E=(PFRAME_DESC)malloc(sizeof(PFRAME_DESC));
      F=(PU32)malloc(sizeof(float));
      codeReturn = PxLGetNextFrame(phCam1, FrameSize, D, E);
      codeReturn = PxLFormatImage(D, E, IMAGE_FORMAT_BMP, NULL, F);
      G=(LPVOID)malloc(*F * sizeof(LPVOID));
      codeReturn = PxLFormatImage(D, E, IMAGE_FORMAT_BMP, G, F);
      FS = new TFileStream(NIC,fmCreate);
      FS->Write(G, *F);
      Sleep(500);
      free(G);
      }
   delete FS;
   codeReturn=PxLSetStreamState(phCam1,STOP_STREAM);
   // Inserire controllo
   codeReturn=PxLUninitialize (phCam1);
   Form2->Canvas->Brush->Bitmap = ImaLoad[0];                   //
Assegna l'immagine al form
   Form2->Canvas->FillRect(Rect(0,0,20000,20000));           //
Dimensiona l'immagine
   Form2->Canvas->Brush->Bitmap = NULL;
   iNIma++;
   strNIma = IntToStr( iNIma);
   Edit1->Text = strNIma;
END:;
}
eri proprio tu che mi avevi aiutato qualche mese fa, veloce e preciso,
complimenti
http://groups.google.it/group/it.comp.programmare.win32/browse_thread/thread/baef95e35882d29c/580f5e56506008f8?lnk=gst&q=TFileStream#580f5e56506008f8

 Questa è la funzione per intero:
Guarda, evito commenti sul codice perchè potrei diventare 
antipatico ed inoltre non è lo scopo della discussione. 
Limitandomi quindi a questi non ben chiari problemi di memoria 
direi che devi controllare bene le varie 
allocazioni/deallocazioni:
      E=(PFRAME_DESC)malloc(sizeof(PFRAME_DESC));
      F=(PU32)malloc(sizeof(float));
E e F dove vengono deallocati?
Ma poi ha senso allocare F in quel modo?
Lo stesso vale per le varie A, B, C, ...
      FS = new TFileStream(NIC,fmCreate);
      FS->Write(G, *F);
      Sleep(500);
      free(G);
Questo free(G) è corretto, ma lo metterei prima dello Sleep.
      }
   delete FS;
Per questo delete confermo quanto detto prima. Deve stare 
all'interno del ciclo. Tieni presente che ovviamente non ho 
controllato tutto il codice e non ho capito cosa faccia per cui 
qualche stupidata posso averla detta.


Lo stesso vale per le varie A, B, C, ...
si non li dealloco, ho provato ma poi il codice salta. Lunedì provo
con la fotocamera collegata a metter il delete FS dentro il ciclo e
riporto gli errori. Per quello che riguarda le allocazioni le ho prese
da un esempio di codice che c'era nell'help delle librerie, in pratica
uno stralcio del programma dato per far funzionare la fotocamera.

Ho provato ad inserie il delete(FS) all'interno del ciclo, risultato:
Project Project1.exe raised exception class EAccessViolation with
message 'Acces violation ar address 011941DE in module 'BORLNDMM.DLL'.
Write of address 00000004'. Process stopped. Use Step or Run to
continue.
La cosa strana è che il messaggio di errore viene dato al terzo giro
del ciclo.

Piccolo aggiornamento. Andando per tentativi son riuscito ad inserire
il delete all'interno del ciclo:
FS= NULL; delete(FS);
Non so perchè ma funziona. Però i problemi permangono, ovvero le
immagini salvate non sono accessibili da altri programmi finchè non
termino l'applicazione.
La memoria tende a saturarsi, però ho riscontrato che questo dipede da
un'altra operazione:
Form2->Canvas->Brush->Bitmap = ImaLoad[i];
Form2->Canvas->FillRect(Rect(0,0,1024,768));
Dopo aver caricato l'immagine nel form, allargo il form a tutto
schermo, è come se venissero caricate le immagini come sfondo al form
e non venissero più scaricate.


Il problema è da qualche altra parte perchè il delete 
all'interno del ciclo ci vuole. Naturalmente non posso provare 
tutto il codice che hai postato, ma questo semplice esempio:
    const int BS = 10;
    TFileStream *FS;
    for (int i = 0; i < 4; i++)
    {
        String S(AnsiString::StringOfChar('A' + i, BS));
        FS = new TFileStream(String(i) + ".txt", fmCreate | 
fmShareDenyWrite);
        FS->Write(S.c_str(), BS);
        delete FS;
    }
è molto simile al pezzo incriminato e non da nessun problema. 
Invece se tolgo 'delete FS' giustamente ci sono dei memory leak.
Hai controllato *tutte* le altre allocazioni dinamiche?
-- 
Stefano Frosio
www.esse-effe.com

 Form2->Canvas->FillRect(Rect(0,0,1024,768));
Strano modo di visualizzare una bitmap su un form. Ti consiglio 
di piazzare un TImage e utilizzare quello.
-- 
Stefano Frosio
www.esse-effe.com

Trovato!!!!! Grazie mille Stefano. Il codice era corretto. Ora
funziona. Entravano in conflitto delle istruzioni eseguite in ordine
diverso, mi spiego:
Il seguente codice non funziona. FS viene inizializzato dopo aver
allocato G. Risultato messagio di errore: "Project D:\BCPP\P020Cam
\Project1.exe faulted with message: 'access violation at 0x40009729:
write of address 0x00030df4. Process Stopped. Use Step or Run to
continue.
for (i=0;i<4;i++)                                           // Ciclo
per la scansione di tutte le immagini
      {
      NIC="";
      NIC.Insert(asCartella, asCartella.Length());
      NIC.cat_printf("im%d.bmp",i);
      E=(PFRAME_DESC)malloc(sizeof(PFRAME_DESC));
      F=(PU32)malloc(sizeof(float));
      codeReturn = PxLGetNextFrame(phCam1, FrameSize, D, E);
      codeReturn = PxLFormatImage(D, E, IMAGE_FORMAT_BMP, NULL, F);
      G=(LPVOID)malloc(*F *sizeof(LPVOID));
      codeReturn = PxLFormatImage(D, E, IMAGE_FORMAT_BMP, G, F);
      FS = new TFileStream(NIC,fmCreate);
      FS->Write(G, *F);
      delete(FS);
      //free(G);
      }
   free(G);
   free(F);
   free(E);
   free(D);
   free(C);
   free(B);
   free(A);
Il seguente codice FUNZIONA. FS viene inizializzato prima di allocare
G:
for (i=0;i<4;i++)                                           // Ciclo
per la scansione di tutte le immagini
      {
      NIC="";
      NIC.Insert(asCartella, asCartella.Length());
      NIC.cat_printf("im%d.bmp",i);
      FS = new TFileStream(NIC,fmCreate);
      E=(PFRAME_DESC)malloc(sizeof(PFRAME_DESC));
      F=(PU32)malloc(sizeof(float));
      codeReturn = PxLGetNextFrame(phCam1, FrameSize, D, E);
      codeReturn = PxLFormatImage(D, E, IMAGE_FORMAT_BMP, NULL, F);
      G=(LPVOID)malloc(*F *sizeof(LPVOID));
      codeReturn = PxLFormatImage(D, E, IMAGE_FORMAT_BMP, G, F);
      FS->Write(G, *F);
      delete(FS);
      //free(G);
      }
   free(G);
   free(F);
   free(E);
   free(D);
   free(C);
   free(B);
   free(A);
Che dire. Spero serva a qualcun altro. Grazie mille ancora.
PS: come si utilizza TImage? :P Scherzo. Lo cerco googolando :D
PS2: Qualche idea sul perchè il secondo funziona e il primo no?

 no?
No, ma probabilmente hai solo spostato il problema da qualche 
altra parte. Non mi meraviglierei se un giorno applicassi una 
modifica e ti saltasse fuori un altro errore che apparentemente 
non c'entra nulla. Nella migliore delle ipotesi la tua 
applicazione ha dei memory leak, il che non è decisamente bello.
-- 
Stefano Frosio
www.esse-effe.com

free(FS) all'interno del ciclo, ma dà errore.
free(FS) è un errore ovvio per quanto detto su.

Non so perchč ma funziona. 
Questo codice non ha senso (delete alla fine lavora su un puntatore
nullo, quindi non fa niente), la memoria ti rimane allocata cosě.

   free(A);
Queste (orribili) free() vanno *DENTRO* il ciclo.
Un consiglio: cerca di capire i perché della programmazione,
altrimenti non farai mai molta strada. Andare di vodoo non serve a
molto.

 molto.
Anche no. Concordo che  free(G), free(F) e free(E) andrebbero dentro
il ciclo, le altre variabili aprono la connessione alla telecamera, e
vengono liberate solo alla fine quando viene chiusa la connessione.
Lunedì provo ad inserire i  free(G), free(F) e free(E) dentro il
ciclo, provando a metterli prima o dopo il delete(FS) tante volte
fosse quello che dà problemi.

fosse quello che dà problemi.
Devi capire il *perché* dei problemi e tu non lo stai facendo.

Problema risolto. Avevo stritto un codice osceno con delle oscene
allocazioni di memoria. Riviso tutto il codice e corretto, funziona
perfettamente, la memoria rimane libera e pulita.
La cosa oscena era questa allocazione G=(LPVOID)malloc(*F *
sizeof(LPVOID)); che poi non riuscivo a deallocare. Trasformata in
fileBuffer = (PU8)malloc(fileSize); funziona perfettamente.
Di seguito il codice corretto:
   U32 nCam;
   HANDLE phCam1;
   CAMERA_INFO e;
   PU32 A=NULL;
   PU32 B=NULL;
   float FrameSize;
   float* C;
   int formatIma;
   LPVOID pFrame;
   FRAME_DESC frameDescriptor;
   U32 fileSize;
   LPVOID fileBuffer;
   long codeReturn;
   TFileStream *FS ;
    NIC="D:\\Acquisizioni\\P\\Prova.bmp";
   codeReturn = PxLGetNumberCameras(NULL, &nCam);		// Conta le camere
connesse al sistema, nCam numero di camere
   codeReturn=PxLInitialize(0, &phCam1);                        //
Acquisisce il puntatore alla camera o i puntatori
   A=(PU32)malloc(sizeof(float));
   B=(PU32)malloc(sizeof(float));
   codeReturn = PxLGetFeature(phCam1, FEATURE_ROI, A, B, NULL);
   C=(float*)malloc(*B * sizeof(float));
   codeReturn = PxLGetFeature(phCam1, FEATURE_ROI, A, B, C);
   FrameSize=C[2]*C[3];
   codeReturn=PxLSetStreamState(phCam1,START_STREAM); // Avvia lo
stream
   pFrame=(LPVOID)malloc(FrameSize*sizeof(PIXEL_FORMAT_MONO8));
   for (i=0;i<4;i++){
      FS = new TFileStream(NIC,fmCreate);
      codeReturn = PxLGetNextFrame(phCam1, FrameSize, pFrame,
&frameDescriptor);
      codeReturn = PxLFormatImage(pFrame, &frameDescriptor,
IMAGE_FORMAT_BMP, NULL, &fileSize);
      fileBuffer = (PU8)malloc(fileSize);
      codeReturn = PxLFormatImage(pFrame, &frameDescriptor,
IMAGE_FORMAT_BMP, fileBuffer, &fileSize);
      FS->Write(fileBuffer, fileSize);
      delete(FS);
      free(fileBuffer);
   }
   free(pFrame);
   free(C);
   free(B);
   free(A);
   codeReturn=PxLSetStreamState(phCam1,STOP_STREAM);
   // Inserire controllo
   codeReturn=PxLUninitialize (phCam1);
Grazie a tutti.