2009-10-01 13 views
7

Quando chiamo un codice C++ non gestito dal mio codice C#, mi sembra di avere una sorta di perdita di memoria.
Il C++ legge i dati da un file usando ifstream.read e li scrive su un vettore.durante la chiamata di codice non gestito dal codice gestito in Windows 7

Questo succede solo dopo l'aggiornamento a Windows 7, non succede su Vista, ma se uso una versione della dll nativa che è stata compilata su Vista, non cambia nulla!
Se eseguo lo stesso codice C++ direttamente, senza l'interopeo gestito, non ci sono perdite di memoria!
Se eseguo il processo gestito, ma all'interno del processo vshost, non ci sono perdite di memoria!

Ecco la firma chiamata:

 [DllImport(DllPath, CharSet = CharSet.Unicode)] 
    [return: MarshalAs(UnmanagedType.I1)] 
    public static extern bool MyMethod(
     int x, 
     string y, 
     string z, 
     bool v, 
     bool w); 

e il nativo uno:

MyDll_Export bool APIENTRY MyMethod(
int x, 
const wchar_t* y, 
const wchar_t* z, 
bool v, 
bool w) 

Quando chiamo da C++, io lo chiamo così:

MyMethod(1, L"My String 1", L"My String 2", true, true) 

Quando ho guarda i contatori delle prestazioni per la memoria gestita e non gestita, vedo che tutta la memoria proviene dal codice non gestito.
Considerando che il marshalling è piuttosto semplice, non capisco perché c'è una differenza tra chiamare il C++ direttamente o tramite C#.
Inoltre, non so perché ciò accadrebbe solo su Windows 7 (entrambe le installazioni di Windows avevano .net 3.5 SP1).

Qualcuno ha un'idea del motivo?

Anche se qualcuno è a conoscenza di uno strumento di creazione profili nativo che funziona su Windows 7, sarei felice di sapere (per ora ho appena stampato per consacrare tutta l'allocazione esplicita della memoria e non ci sono differenze).

+0

LeakDiag [http://mcfunley.com/277/using-leakdiag-to-debug-unmanaged-memory-leaks] o AQTime di AutomatedQA possono eseguire analisi delle perdite non gestite. –

+0

Quale contatore delle prestazioni si usa per misurare il consumo di memoria? –

+0

Hai taggato la domanda "vshost.exe". L'applicazione viene eseguita in Visual Studio quando si misura il consumo di memoria? –

risposta

5

Sono sicuro che il problema è relativo al marshalling dei tipi di dati C# nelle loro parti contatore C++. Poiché stai eseguendo il marshalling del valore restituito bool su un valore di 1 byte con segno, forse dovresti fare lo stesso con gli argomenti della funzione? Il tipo booleano C# è di 4 byte, forse ci stai perdendo?

Inoltre, può essere utile specificare il tipo non gestito per le stringhe.

[DllImport(DllPath, CharSet = CharSet.Unicode)] 
[return: MarshalAs(UnmanagedType.I1)] 
public static extern bool MyMethod(
     int x, 
     [MarshalAs(UnmanagedType.LPWStr)] 
     [In] string y, 
     [MarshalAs(UnmanagedType.LPWStr)] 
     [In] string z, 
     [MarshalAs(UnmanagedType.I1)] 
     bool v, 
     [MarshalAs(UnmanagedType.I1)] 
     bool w); 

Una spiegazione per la commentor:

For the C++ bool type:

In generale, un valore zero o nullo puntatore viene convertito falso, qualsiasi altro valore viene convertita in true.

...

La libreria standard C++ 1998 definisce una specializzazione del vettore modello per bool. La descrizione della classe indica che l'implementazione deve contenere gli elementi in modo che ogni bool utilizza solo un bit di memoria.

Quindi, praticamente qualunque valore si usi, si otterrà un booleano C++ con il valore true o false.

+0

Se il bool non corrisponde alle dimensioni non sarebbe una perdita di memoria, ma più probabilmente una violazione di accesso o una sorta di corruzione dello stack. – user7116

+0

bel file scott, C# marshals bool come 4 byte. L'attributo marshalas mancava per v e w. http://blogs.msdn.com/oldnewthing/archive/2009/08/13/9867383.aspx –

+0

err. significato 'trovare' –

2

Sfortunatamente una volta coinvolte le stringhe, il marshalling non è semplice.

Avremo bisogno di altri dati per aiutarti a rintracciare questo problema. Potete fornire il seguente Signature

  • Native Metodo
  • Come è la memoria per le stringhe gestito in codice nativo?
  • Forse l'esempio C++ in cui si utilizza l'API?

EDIT

Prova la seguente firma. Questo dice il CLR di non schierare la memoria in entrambe le direzioni, ma invece passare solo i dati.

[DllImport(DllPath, CharSet = CharSet.Unicode)] 
    [return: MarshalAs(UnmanagedType.I1)] 
    public static extern bool MyMethod(
      int x, 
      [In] string y, 
      [In] string z, 
      bool v, 
      bool w); 
+0

grazie, domanda aggiornata, le stringhe passate sono costanti. –

+0

il [In] non ha aiutato, perché sarebbe cambiato tra Vista e Windows 7? inoltre, non ho detto che chiamo questo metodo solo una volta. –

1

ho trovato l'uso del CLR Profiler utile quando trovare la mia perdita di memoria.

0

Sei sicuro che ci sia una perdita di memoria?

Qual è la vostra base per determinare la perdita di memoria. Dici che puoi vederlo dai contatori delle prestazioni, ma cosa osservi effettivamente?Vedi una curva che sale in modo crescente o che si assesta su un livello elevato? Un elevato consumo di memoria è spesso confuso per una perdita di memoria.

btw. Puoi pubblicare anche la definizione della funzione C++?

+0

Vedo una curva in continuo aumento. ho postato la definizione della funzione C++, se intendi il corpo, quindi legge solo i dati da un file usando ifstream.read –

Problemi correlati