2012-01-26 7 views
7

Scrivo un modulo in C# che esporta alcune funzioni da utilizzare in C. Ho bisogno di allocare memoria per alcune strutture da passare tra C < -> C#.Qualche differenza tra malloc e Marshal.AllocHGlobal?

Quello che alloco in C lo faccio con malloc, e in C# lo faccio con Marshal.AllocHGlobal() (per allocare la memoria non gestita da passare a C).

C'è qualche problema se ho liberato() la memoria allocata con Marshal.AllocHGlobal e se rilascio memoria con Marshal.FreeHGlobal() che è stato allocato con malloc?

Grazie

+0

Grazie per tutte le risposte – bzamfir

+0

Grazie. In realtà quello che ho fatto è stato creare nelle mie funzioni lib esportate AllocateMem e FreeMem, che ho raccomandato di usare chiamando programmi, quando si creano strutture passate alla lib. Ma mi stavo chiedendo di non rispettare questa regola e passare alla mia lib alcune strutture allocate con malloc (o qualsiasi altra cosa), cosa dovrebbe accadere? – bzamfir

+0

Il problema è che le strutture hanno alcuni puntatori al char (per le stringhe) che devo allocare e passare al codice chiamante. E se il codice chiamante tenta di liberare quella memoria con free()? Ecco perché ho creato FreeMem, che ho implementato con FreeHGlobal, per essere usato per rilasciare memoria nel chiamare prog. Altrimenti è la responsabilità del programmatore del codice chiamante. – bzamfir

risposta

15

La regola d'oro è che si deve rilasciare dallo stesso mucchio che è stato utilizzato per allocare la memoria.

Se lo si assegna con malloc(), è necessario deallocarlo con lo free() dallo stesso C RTL. E allo stesso modo sul lato gestito, AllocHGlobal() dovrebbe essere bilanciato da FreeHGlobal().

Ora, AllocHGlobal() viene implementato chiamando la funzione Win32 LocalAlloc. Quindi è possibile liberare tale memoria con una chiamata a LocalFree sul lato nativo. E viceversa.

Se si desidera utilizzare un heap condiviso tra nativo e gestito, è più comune utilizzare l'heap COM. Sul lato nativo utilizzare CoTaskMemAlloc() e CoTaskMemFree(). Sul lato gestito utilizzare Marshal.AllocCoTaskMem() e Marshal.FreeCoTaskMem().

Tuttavia, si dovrebbe evitare di progettare il sistema in questo modo. È molto più semplice attenersi a una regola che tutta la memoria allocata nel lato gestito viene deallocata lì, e allo stesso modo per il lato nativo. Se non segui questa regola, presto perderai traccia di chi è responsabile di cosa.

4

Potrebbe esserci o non esserci un problema - questo dipende totalmente dall'implementazione. Mai fare affidamento su un dettaglio di implementazione per la funzionalità della tua app!

quindi vi consiglio non utilizzare Marshal.AllocHGlobal(), malloc(), Marshal.FreeHGlobal() e free() trasversale.

Un esempio, dove ti imbatterai in guai seri è se usi una libreria, che faccia una specie di fantasia malloc()/free() magica - potresti persino non saperlo.

+1

No, semplicemente non funziona affatto! Non esiste o potrebbe non esserlo! –

+0

@DavidHeffernan Interessante! Avevamo questo in un'app e normalmente funzionava bene in Mono, le cose iniziarono a rompersi con librerie fantasiose, così abbiamo studiato. –

+1

Sembra che in realtà non funzioni. Ma Mono potrebbe essere una bestia diversa. Sto assumendo MS.netto e quindi la finalità del mio commento. –