|
|
|
|
Strumenti |
10-05-2021, 11:19 | #1 |
Junior Member
Iscritto dal: May 2021
Messaggi: 1
|
C++ gestione memoria
Ciao a tutti.
Ho un dubbio che probabilmente è banale. Allora io ho un processo che, in base ad un evento chiama un metodo di una classe. Il metodo è simile a questo, crea un messagio e lo invia sulla rete: Codice:
void Manager::doOp() { for(int i=0; i <=10; i++) { Message* msg = new Message(); send(msg); } } Ma nel momento in cui il processo che possedeva l'istanza della classe manager viene terminato, e ne viene poi creato uno nuovo senza terminare il programma. La parte di memoria occupata dai messaggi creati viene liberata? Grazie. |
10-05-2021, 12:50 | #2 |
Senior Member
Iscritto dal: May 2005
Città: Trieste
Messaggi: 2275
|
ciao
senza sapere cosa fa esattamente il metodo send si può solo ipotizzare(magari questo metodo è delegato al cleanup dopo l'effettiva spedizione...), comunque sì, in linea di massima c'è un memleak e va risolto o con una delete oppure, scelta migliore usando smart pointer che semplificano enormemente la vita in operazioni di questo tipo solitamente la memoria heap è "per-process", quindi viene rilasciata alla chiusura del processo
__________________
neo mini v2 / asus strix z490i / 10600k@? / uh12s / rx6700xt / 32gb ddr4@3200 / sandisk 250 + asenno 1tb / lenovo g34w
trattative concluse : tante... |
18-05-2021, 08:47 | #3 |
Senior Member
Iscritto dal: Jul 2007
Città: Sicilia
Messaggi: 5428
|
Il principio di buona programmazione prevede che la classe che crea un puntatore ne diventa l'owner, quindi dovrebbe essere responsabile anche della sua cancellazione. Quindi una classe/funzione che accetta un puntatore come argomento non dovrebbe cancellarla. Questo principio evita problemi come utilizzo di dangling pointer o memory leak, perche' ogni utilizzatore del puntatore ha la sua responsabilita'.
Se per motivi di design si DEVE spostare l'ownership di un puntatore (ad esempio perche' viene creato da una factory), sarebbe opportuno dirlo esplicitamente, ad esempio con l'utilizzo di un unique_ptr che non puo' essere copiato ma soltanto spostato, quindi passarlo ad una funzione o ad una classe significa esplicitamente che lei ne acquisisce la proprieta' e ne diventa responsabile. Quindi nel tuo caso "send()" non dovrebbe cancellare il puntatore, ma dovrebbe farlo il tuo manager nel ciclo. Se dovesse per qualche motivo cancellarlo il "send()" allora invece di "Message*" dovresti fare un "std::unique_ptr<Message>" e passarlo per move al send. In questo modo si invalida il puntatore del ciclo for dato che viene "mosso" e non "copiato" all'interno del send, la cui signature diventa "void send(std::unique_ptr<Message>&& message", e quando finira' il suo scope verra' automaticamente cancellato.
__________________
Non abbiamo ereditato il mondo dai nostri padri L'abbiamo preso in prestito dai nostri figli Ultima modifica di jepessen : 18-05-2021 alle 08:49. |
27-06-2021, 12:42 | #4 |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5964
|
Scusa l'ignoranza, ma se send() non prende possesso di quella memoria, a che serve allocarla sullo heap?
Non ti basta fare questo? Codice:
void Manager::doOp() { for(int i=0; i <=10; i++) { Message msg; send(&msg); } }
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
28-06-2021, 21:52 | #5 | |
Member
Iscritto dal: Dec 2006
Messaggi: 33
|
Quote:
Ad esempio, se la send() avvenisse in maniera asincrona il rischio è che al momento dell'invio venga letta memoria non valida (msg verrebbe cancellata alla chiusura del blocco in cui è dichiarata). In un caso del genere, deve avvenire un trasferimento di ownership della memoria. Come detto, meglio usare unique_ptr e trasferire l'ownership alla funzione send() ma, secondo me, con le informazioni a disposizione è difficile dare una risposta più precisa ... Ultima modifica di Lampo89 : 28-06-2021 alle 22:33. |
|
28-06-2021, 22:17 | #6 | |
Member
Iscritto dal: Dec 2006
Messaggi: 33
|
Quote:
Solamente, modificherei invece la signature del metodo send() in: send(std::unique_ptr<Message> message) in modo da eseguire esplicitamente il passaggio di ownership del puntatore alla funzione send(). Nel modo in cui proponi, passeresti comunque una referenza (una ref ad un temporaneo) ma, in assenza di ulteriori move del puntatore nel corpo della funzione, il trasferimento di ownership non avverrebbe. questo esempio dovrebbe chiarificare, nota come dopo prima chiamata (argomento unique_ptr&&) lo smart pointer è ancora valido, mentre dopo la seconda è nullptr in seguito alla costruzione dell'argomento via move constructor https://gist.github.com/Lampo89/8194...ec47777ba3454c Non c'entra nulla, ma giro un link su best practices riguardo la gestione della memoria (il link punta al caso che facevo notare). ci sono molti altri suggerimenti interessanti che vale davvero la pena leggere, opinione mia http://isocpp.github.io/CppCoreGuide...ip-of-a-widget Ultima modifica di Lampo89 : 28-06-2021 alle 23:02. |
|
29-06-2021, 10:09 | #7 | |
Senior Member
Iscritto dal: Jul 2007
Città: Sicilia
Messaggi: 5428
|
Quote:
Anche le CppCoreGuidelines sono veramente un'ottima lettura, ma a mio avviso il fatto di avere un unico .md rende la lettura pesante, ed anche il file. Preferisco convertirlo in PDF per poterlo leggere con piu' naturalezza, riaprire il file per ricominciare a leggere da dove avevo interrotto etc... Anche abilitare il check delle regole cpp sugli IDE come visual studio e' molto interessante, e permette di analizzare i "code smell" il prima possibile.
__________________
Non abbiamo ereditato il mondo dai nostri padri L'abbiamo preso in prestito dai nostri figli |
|
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 08:06.