Italiano - English

Falso memory leak con OpenCV e MFC in Visual Studio

Il problema dei falsi memory leak tra OpenCV e MFC con Visual Studio è noto da tempo. In questa pagina viene descritto come risolvere questo fastidioso problema.

VisualStudio segnala numerosi memory leak al termine di una applicazione MFC che utilizza OpenCV. E' molto probabile che questi memory leak siano "falsi allarmi" causati dalla sequenza di caricamento delle DLL.

All'avvio di una applicazione MFC vengono caricate prima le eventuali DLL utente (OpenCV o altre) e poi le DLL relative ad MFC. Il rilascio delle DLL avviene con la sequenza inversa, quindi prima MFC poi le altre DLL.

Per le applicazioni MFC, il controllo per i memory leaks di Visual Studio viene eseguito dopo il rilascio dopo il MFC. Siccome in memoria sono ancora presenti le DLL utente, il controllo riscontra la presenza di memoria ancora in uso quindi segnala un memory leaks.

Si tratta di falsi memory leak perchè il controllo avviene prima che tutte le le altre DLL in uso vengano rilasciate e possano liberare la memoria occupata.

In quanto "falsi allarmi" possono essere ignorati. Il punto è che non è possibile stabilire a priori quali memory leaks segnalati sono falsi allarmi e quali no. E' bene quindi rimuovere i falsi allarmi ed assicurarsi che nessun memory leak venga segnalato al termine della propria applicazione.

Per rimuovere i falsi allarmi esistono due soluzioni al problema:

  • Opzione 1) Utilizzare le versioni statiche delle librerie MFC (o OpenCV)
  • Opzione 2) Utilizzare il caricamento ritardato delle DLL

Utilizzare MFC statico

L'utilizzo delle librerie statiche di MFC risolve il problema perché MFC diventa parte integrante dell'applicazione e non viene più caricata come DLL. Il controllo per il memory leak viene eseguito al termine dell'applicazione quindi dopo che tutte le DLL sono state rilasciate.

In questo caso eventuali memory leak segnalati sono reali e dovuti a mancate de-allocazioni nel nostro codice o nel codice delle DLL utilizzate.

Per utilizzare la versione statica di MFC è sufficiente attivare l'apposita l'opzione in Project Properties > Configuration Properties > General > Use of MFC >Use MFC in a Static Library.

Tralasciamo di descrivere i pro e contro di questa scelta, che per altro molti fanno.

Utilizzare il caricamento ritardato

Visual Studio dispone di una opzione per il caricamento ritardato delle DLL. E' possibile imporre il caricamento ritardato delle DLL utente tra cui anche OpenCV.

In questo modo le DLL indicate vengono caricate al momento dell'utilizzo (quindi dopo le MFC). Siccome il rilascio delle librerie avviene con sequenza inversa al caricamento, le DLL utente (e relativa memoria) verranno rilasciate prima delle MFC.

Il controllo per il memory leak troverà una memoria pulita.

Anche in questo caso eventuali memory leak segnalati sono reali e dovuti a mancate de-allocazioni nel nostro codice o nel codice delle DLL utilizzate.

Configurare OpenCV per il caricamento ritardato

Per utilizzare il caricamento ritardato di OpenCV è necessario elencare tutte le DLL utilizzate in:

Project Properties > Configuration Properties > Linker > Input > Delay Loaded Dlls.

Nel progetto di Visual Studio sono indicati i moduli di libreria da utilizzare. In OpenCV, ogni modulo è un file LIB che viene elencato nelle dipendenze del linker. Al momento della compilazione il linker decide quale LIB utilizzare.

Ad ogni modulo LIB utilizzato corrisponde una DLL che va elencata nel caricamento ritardato.

Warning  4199

E' frequente impostare il progetto di Visual Studio per poter utilizzare tutti i moduli offerti da OpenCV. Se, come per i file LIB elencano tutte le DLL offerte da OpenCV, al momento della compilazione Visual Studio mostra un warning per ogni DLL elencata ma non utilizzata:

1>LINK : warning LNK4199: /DELAYLOAD:opencv_features2d320d.dll ignored; no imports found from ...
1>LINK : warning LNK4199: /DELAYLOAD:opencv_...

E' possibile disabilitare questo warning impostando opzione /ignore:4199 in

Project Properties > Configuration Properties > Linker > Command Line > Additional Options.

Debug o Relase ?

E' possibile specificare opzioni differenti per le due configurazioni di Ddebug o Release. Ad esempio è possibile utilizzare il caricamento ritardato solo nella versione di Debug allo scopo di isolare e visualizzare eventuali memory leaks reali generati dal nostro codice.

Una volta appurato che la versione di Debug è esente da memory leaks possiamo utilizzare il caricamento normale per la versione di Release e ignorare i falsi allarmi.

Lo sviluppatore può decidere quale scelta operare e se configurare il caricamento ritardato per tutte le configurazioni.

Vota questa pagina:

0 Commenti:

Lascia il tuo commento:

Note:
  • La tua email non è obligatoria e non sarà visibile in alcun modo
  • Si prega di inviare solo commenti relativi a questa pagina
  • Commenti inappropriati o offensivi saranno modificati o eliminati
  • Codici HTML non sono consentiti. Prego usare i BB code:
    [b]bold[/b], [u]underline[/u], [i]italic[/i], [code]code[/code]
Il codice, le illustrazioni e gli esempi riportati in questa pagina sono solo a scopo illustrativo. L'autore non prende alcuna responsabilità per il loro utilizzo da parte dell'utente finale.
Questo materiale è di proprietà di Pk Lab ed è utilizzabile liberamente a condizione di citarne la fonte.