Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 17
  1. #1
    Utente di HTML.it L'avatar di colde
    Registrato dal
    Feb 2001
    Messaggi
    1,802

    PChar e allocazioni/deallocazioni di memoria

    Ciao Alka,
    mi viene un dubbio atroce:
    nella DLL elaboro dei dati e li inserisco una variabile di tipo string, dopodichè alloco memoria nel buffer e copio il contenuto della stringa in una variabile PChar che viene restituita dalla DLL e letta dal software esterno, in questo modo:

    codice:
    //Alloco memoria per contenere il valore di ritorno della funzione da passare al software
    GetMem(Result,Length(ResponseBox));
    //Copio il valore di ritorno nella variabile che la funzione ritorna
    Result := StrPCopy(Result, ResponseBox);
    ResponseBox è la varibile di tipo string mentre result è naturalmente la variabile usata come ritorno della funzione dalla DLL all'applicazione esterna.

    Sia nella DLL che nell'applicazione esterna non ho inserito alcun deallocamento di memoria ma dai test che ho fatto non ricevo mai alcun errore anche se richiamo la funzione N volte.

    Con questo sistema sono obbligato a deallocare la memoria manualmente oppure lo fa già delphi in modo automatico? Se dovessi obbligatoriamente deallocare la memoria manualmente, come potrei fare? Nella variabile di ritorno alla funzione non assegno un indirizzo di memoria ma il contenuto della variabile ResponseBox e in caso fossi obbligato a deallocare memoria lo vorrei fare da DLL e non da software esterni, il problema è che non saprei come gestirlo. Mi sai dare qualche delucidazione?
    Come potrei verificare se la DLL mi ciuccia memoria all'infinito? In altre parole,come posso verificare quanta memoria viene allocata dalla DLL?

    Grazie mille
    www.beppegrillo.it
    Il blog di Beppe!!

  2. #2
    Utente di HTML.it L'avatar di colde
    Registrato dal
    Feb 2001
    Messaggi
    1,802
    UP!!
    www.beppegrillo.it
    Il blog di Beppe!!

  3. #3
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    La memoria allocata per le stringhe viene gestita dinamicamente da Delphi, al contrario la memoria recuperata con GetMem è un buffer totalmente gestito dallo sviluppatore (e va quindi deallocato, a piacere, quando non serve più, con FreeMem).

    Se copi una stringa String in un buffer, quando questa viene deallocata il buffer contenente la copia sopravvive, ovviamente, perché la sua gestione è affidata allo sviluppatore.

    Se non recuperi la memoria allocata con GetMem, è chiaro che si tratta di un "memory leak" e il tuo programma, ad ogni chiamata, allocherà una quantità sempre maggiore di memoria.

    Per informazioni ed esempi sulla GetMem, leggi qui (ci sono informazioni anche per le funzioni correlate).

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  4. #4
    Utente di HTML.it L'avatar di colde
    Registrato dal
    Feb 2001
    Messaggi
    1,802
    Quindi mi è chiaro che nel mio caso devo gestire io la deallocazione ma non mi è chiaro ancora come devo fare. Mi sta bene il FreeMem ma in base al codice che ho postato, come la posso impostare la deallocazione? Correggimi se sbaglio: dalla DLL mi ritorna il PChar contenente la stringa copiata, il PChar in realtà non contiene la stringa vera e propria ma l'indirizzo del buffer con al suo interno la stringa, giusto? Se così fosse, una volta che recupero la stringa dal software posso richiamare una funzione dalla DLL che mi deallochi il buffer ma cosa gli passo nella funzione?

    Faccio un esempio, dimmi se è corretto:

    Codice Software
    codice:
    procedure TForm1.Button1Click(Sender: TObject);
    Var
      TextReturn: PChar;
    begin
    //Recupero il valore dalla DLL e lo assegno ad una variabile PChar allocata dinamicamente         
    TextReturn := Polling(PChar('PIPPO'));
    //Visualizzo il contenuto di PChar in un TMemo
    Memo1.Lines.Add(TextReturn);
    //Richiamo la funzione dalla DLL che mi libera la memoria allocata con GetMem dalla funzione Polling() richiamata in precedenza
    FreeMemory(?????) ----> QUI COSA METTO?
    end;
    Altro dubbio che mi è venuto, al posto di usare una funzione per il deallocamento del buffer (la funzione mi ritorna un valore mentre in questo caso non servirebbe) potrei usare una procedura? Comporta problemi di "portabilità" con altri linguaggi?

    Grazie mille per la pazienza.
    www.beppegrillo.it
    Il blog di Beppe!!

  5. #5
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    Originariamente inviato da colde
    Quindi mi è chiaro che nel mio caso devo gestire io la deallocazione ma non mi è chiaro ancora come devo fare. Mi sta bene il FreeMem ma in base al codice che ho postato, come la posso impostare la deallocazione?
    Ti avevo postato il link mica per nulla: c'era un esempio chiaro.

    Alla funzione FreeMem si passa il puntatore al buffer di caratteri PChar.

    Originariamente inviato da colde
    Altro dubbio che mi è venuto, al posto di usare una funzione per il deallocamento del buffer (la funzione mi ritorna un valore mentre in questo caso non servirebbe) potrei usare una procedura? Comporta problemi di "portabilità" con altri linguaggi?
    No, nessun problema, è corretto usare una procedura in tali casi.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  6. #6
    Utente di HTML.it L'avatar di colde
    Registrato dal
    Feb 2001
    Messaggi
    1,802
    Originariamente inviato da alka
    Ti avevo postato il link mica per nulla: c'era un esempio chiaro.

    Alla funzione FreeMem si passa il puntatore al buffer di caratteri PChar.
    Si ma visto che il mio puntatore è la variabile Result della funzione non posso farlo in quel modo. Devo creare una nuova variabile pointer in cui inserire l'inidirzzo di Result per passarlo alla DLL che me lo dealloca? Oppure, se faccio in questo modo è la stessa cosa?

    TextReturn := Polling(PChar('PIPPO'));
    Memo1.Lines.Add(TextReturn);
    FreeMem(TextReturn);

    Però in questo modo dealloco TextReturn, non la variabile Result della funzione e dato che ho allocato memoria a Result e non a TextReturn, ho una vaga sensazione che questo non vada bene. Confermi?

    Scusami ma ho bisogno di capire bene questa cosa e finchè ho dubbi non mi sento sicuro di seguire la strada giusta.
    www.beppegrillo.it
    Il blog di Beppe!!

  7. #7
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    Originariamente inviato da colde
    Devo creare una nuova variabile pointer in cui inserire l'inidirzzo di Result per passarlo alla DLL che me lo dealloca? Oppure, se faccio in questo modo è la stessa cosa?
    TextReturn := Polling(PChar('PIPPO'));
    Memo1.Lines.Add(TextReturn);
    FreeMem(TextReturn);
    In questo modo è perfetto. L'uso di una funzione apposita nella DLL che fa questo mestiere avrebbe solamente lo scopo di rendere la cosa più elegante (per evitare la chiamata a FreeMem che potrebbe risultare meno intuitiva, da parte di terzi, rispetto all'uso di una funzione apposita della DLL che fa solo quello).

    Originariamente inviato da colde
    Però in questo modo dealloco TextReturn, non la variabile Result della funzione e dato che ho allocato memoria a Result e non a TextReturn, ho una vaga sensazione che questo non vada bene. Confermi?
    Tu non deallochi le variabili, a quello ci pensa già il codice inserito nel compilatore (infatti, non hai mai dovuto scrivere codice per "distruggere" variabili intere e simili).

    Quello che deallochi con FreeMem è il buffer puntato dalla variabile.

    Result è solo un segnaposto per il valore di ritorno della funzione; quando essa termina, il valore viene assegnato (o perduto) alla variabile preposta. Nel caso in esame, viene restituito un puntatore, Result esce dallo "scope" e quindi viene deallocata la memoria riservata al contenimento del puntatore, il cui valore passa alla variabile che ottiene il ritorno dalla funzione, che utilizza quel puntatore e, successivamente, lo passa ad un'altra procedura che lo usa per risalire al buffer da allocare.

    Confondi il rilascio della memoria delle variabili con il rilascio della memoria allocata con GetMem; nelle prime ci sono solo i riferimenti (puntatori) al buffer creato con GetMem; con FreeMem, usando il puntatore, distruggi il buffer.
    Le variabili che contengono il puntatore, che non è altro che un valore intero, sono gestite in automatico, come sempre.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  8. #8
    Utente di HTML.it L'avatar di colde
    Registrato dal
    Feb 2001
    Messaggi
    1,802
    Ho fatto come descritto ma c'è ancora un'ultima cosa che non mi è chiara:
    questa è la procedura che dovrebbe essere corretta
    da software richiamo la funzione DLL che recupera i dati dalla seriale --> nella DLL alloco la memoria manualmente --> passo il valore di ritorno della funzione al software --> leggo il valore e lo stampo --> richiamo la procedura che dealloca il buffer
    Se a questo punto richiamo un'altra volta la mia funzione per recuperare i dati dalla seriale per ricominciare il ciclo appena descritto, mi ritorna un access violation. Perchè? Ad ogni chiamata io alloco memoria e alla fine la dealloco sempre. Non capisco. Scusami ma sono un po tardo.
    Da debug il comportamento è alquanto anomalo.
    www.beppegrillo.it
    Il blog di Beppe!!

  9. #9
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    Originariamente inviato da colde
    Se a questo punto richiamo un'altra volta la mia funzione per recuperare i dati dalla seriale per ricominciare il ciclo appena descritto, mi ritorna un access violation. Perchè?
    L'errore può essere dovuto anche ad altre istruzioni che non hanno a che vedere con la gestione di quel buffer. Visto che non è la prima volta che riporti sviste, come nel caso della creazione dinamica di componenti, io darei una ricontrollatina al codice.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  10. #10
    Utente di HTML.it L'avatar di colde
    Registrato dal
    Feb 2001
    Messaggi
    1,802
    Può essere, non lo metto in dubbio ma mi pare strano che senza il FreeMem funzioni correttamente, in fondo dealloco semplicemente il buffer ma non credo che possa intaccare altro. Comunque sto facendo il debug e ho notato un comportamento stranissimo, vedrò di testare il codice ulteriormente e verificare eventuali mancanze. :master:
    www.beppegrillo.it
    Il blog di Beppe!!

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