Domanda

Questo è un po' ipotetico e grossolanamente semplificato ma...

Si supponga un programma che chiamerà funzioni scritte da terze parti.Si può presumere che questi partiti non siano ostili, ma non si può presumere che siano “competenti”.Ogni funzione accetterà alcuni argomenti, avrà effetti collaterali e restituirà un valore.Non hanno uno stato mentre non sono in esecuzione.

L'obiettivo è garantire che non possano causare perdite di memoria registrando tutti i malloc (e simili) e quindi liberando tutto dopo l'uscita dalla funzione.

È possibile?È pratico?

p.s.La parte importante per me è garantire che non persistano allocazioni, quindi i modi per rimuovere le perdite di memoria senza farlo non mi sono utili.

È stato utile?

Soluzione

Non specifichi il sistema operativo o l'ambiente, questa risposta presuppone Linux, glibc e C.

È possibile impostare __malloc_hook, __free_hook e __realloc_hook in modo che puntino a funzioni che verranno chiamate rispettivamente da malloc(), realloc() e free().C'è una pagina man __malloc_hook che mostra i prototipi.È possibile aggiungere allocazioni di tracce in questi hook, quindi tornare per consentire a glibc di gestire l'allocazione/deallocazione della memoria.

Sembra che tu voglia liberare eventuali allocazioni live quando ritorna la funzione di terze parti.Esistono modi per fare in modo che gcc inserisca automaticamente le chiamate ad ogni entrata e uscita di funzione utilizzando -finstrument-functions, ma penso che sarebbe inelegante per quello che stai cercando di fare.Puoi fare in modo che il tuo codice chiami una funzione nella libreria di monitoraggio della memoria dopo aver chiamato una di queste funzioni di terze parti?Potrai quindi verificare se ci sono allocazioni che la funzione di terze parti non ha già liberato.

Altri suggerimenti

Innanzitutto, devi fornire i punti di ingresso per malloc() E free() e amici.Poiché questo codice è già compilato (giusto?) non puoi dipendere #define reindirizzare.

Quindi puoi implementarli in modo ovvio e registrare che provengono da un determinato modulo collegando quelle routine a quei moduli.

Il modo più veloce prevede nessuna registrazione. Se la quantità di memoria utilizzata è limitata, perché non pre-allocare tutto l'"heap" di cui avranno mai bisogno e scriverne un allocatore?Poi, una volta terminato, libera l'intero "heap" e il gioco è fatto!Potresti estendere questa idea a più heap se è più complessa di così.

Se hai davvero bisogno di "registrare" e non creare il tuo allocatore, ecco alcune idee.Uno, usa una tabella hash con puntatori e concatenamento interno.Un altro sarebbe quello di allocare spazio extra davanti a ogni blocco e inserire lì la propria struttura contenente, ad esempio, un indice nella "tabella di registro", quindi mantenere un elenco libero di voci della tabella di registro (come uno stack in modo da ottenerne uno libero o rimetterne uno libero è O(1)).Questo richiede più memoria ma dovrebbe essere veloce.

È pratico?Penso di sì, purché il colpo di velocità sia accettabile.

È possibile eseguire le funzioni di terze parti in un processo separato e chiudere il processo una volta terminato l'utilizzo della libreria.

Una soluzione migliore rispetto al tentativo di registrare i malloc potrebbe essere quella di sandboxare le funzioni quando le chiami: dare loro l'accesso a un segmento fisso di memoria e quindi liberare quel segmento quando la funzione ha terminato l'esecuzione.

L'utilizzo non limitato e incompetente della memoria può essere altrettanto dannoso quanto il codice dannoso.

Non puoi semplicemente forzarli ad allocare tutta la loro memoria nello stack?In questo modo sarebbe garantito che venga liberato una volta terminata la funzione.

In passato ho scritto una libreria software in C che aveva un sottosistema di gestione della memoria che conteneva la possibilità di registrare allocazioni e libere e di abbinare manualmente ciascuna allocazione e libera.Questo era di qualche utilità quando si cercava di trovare perdite di memoria, ma era difficile e richiedeva molto tempo da usare.Il numero di registri era enorme e ci voleva molto tempo per comprenderli.

Detto questo, se la tua libreria di terze parti dispone di ampie allocazioni, è molto probabile che non sia pratico tenerne traccia tramite la registrazione.Se utilizzi un ambiente Windows, suggerirei di utilizzare uno strumento come Purify[1] o BoundsChecker[2] che dovrebbe essere in grado di rilevare perdite nelle librerie di terze parti.L'investimento nello strumento dovrebbe ripagarsi in termini di tempo risparmiato.

[1]: http://www-01.ibm.com/software/awdtools/purify/ Purificare

[2]: http://www.compuware.com/products/devpartner/visualc.htm Controllo dei limiti

Dato che sei preoccupato per le perdite di memoria e parli di malloc/free, presumo che tu sia in C.Presumo anche, in base alla tua domanda, che tu non abbia accesso al codice sorgente della libreria di terze parti.

L'unica cosa che mi viene in mente è esaminare il consumo di memoria della tua app prima e dopo la chiamata, registrare i messaggi di errore se sono diversi e convincere il fornitore di terze parti a correggere eventuali perdite riscontrate.

Se hai soldi da spendere, considera l'utilizzo di Purify per tenere traccia dei problemi.Funziona a meraviglia e non richiede codice sorgente o ricompilazione.Sono disponibili anche altre librerie malloc di debug più economiche.Electric Fence è un nome che ricordo.Detto questo, anche gli hook di debug menzionati da Denton Gentry sembrano interessanti.

Se sei troppo povero per Purify, prova Valgrind.È molto meglio di 6 anni fa ed è molto più facile immergersi rispetto a Purify.

Microsoft Windows fornisce (utilizza SUA se è necessario un POSIX), molto probabilmente, l'infrastruttura heap+ (altra API nota per utilizzare l'heap) più avanzata di qualsiasi sistema operativo disponibile oggi.

gli hook di debug __malloc() e le interfacce di debug CRT associate sono utili per i casi in cui si dispone del codice sorgente per i test, tuttavia spesso possono perdere le allocazioni da parte delle librerie standard o di altro codice collegato.Ciò è previsto poiché si tratta dell'infrastruttura di debug dell'heap di Visual Studio.

gflags è un insieme molto completo e dettagliato di funzionalità di debug incluso in Windows da molti anni.Funzionalità avanzate per casi d'uso solo di origine e binaria (in quanto è l'infrastruttura di debug dell'heap del sistema operativo).

Può registrare tracce di stack complete (ripaginazione delle informazioni simboliche in un'operazione post-elaborazione), di tutti gli utenti dell'heap, per tutti i punti di ingresso che modificano l'heap, in serie se necessario.Inoltre, può modificare l'heap con casi patologici che possono allineare l'allocazione dei dati in modo tale che la protezione della pagina offerta dal sistema VM sia assegnata in modo ottimale (ad es.alloca il blocco heap richiesto alla fine di una pagina, in modo che venga rilevato anche un singolo byte in eccesso al momento dell'overflow.

umdh è uno strumento che può aiutare a valutare lo stato in vari checkpoint, tuttavia i dati vengono continuamente accumulati durante l'esecuzione del target o non è un semplice arresto del debug di checkpoint nel contesto tradizionale.Anche, AVVERTIMENTO, L'ultima volta che ho controllato almeno, la dimensione totale del buffer circolare che memorizza le informazioni sullo stack, per ogni richiesta è piuttosto piccola (64k voci (voci+stack)), quindi potrebbe essere necessario eseguire il dump rapidamente per gli utenti di heap pesanti.Esistono altri modi per accedere a questi dati, ma umdh è abbastanza semplice.

NOTA ci sono 2 modalità;

  1. MODO 1, umdh {-p:ID-Processo|-pn:NomeProcesso} [-f:NomeFile] [-g]
  2. MODO 2, umdh [-d] {File1} [File2] [-f:Nome file]

    Non so quale follia abbia preso lo sviluppatore che ha scelto di alternare tra lo specificatore di argomenti -p:foo e l'ordinamento nudo degli argomenti, ma può creare un po' di confusione.

L'SDK di debug funziona con una serie di altri strumenti, memsnap è uno strumento che apparentemente si concentra sulle perdite di memoria e simili, ma non l'ho usato, il tuo chilometraggio può variare.

Esegui gflags senza argomenti per la modalità UI, +arg e /args lo sono diverso anche "modalità" di utilizzo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top