2009-10-01 21 views
7

Cuando llamo a un código C++ no administrado desde mi código C#, parece que tengo algún tipo de pérdida de memoria.
El C++ lee datos de un archivo utilizando ifstream.read y lo escribe en un Vector.pérdida de memoria al llamar código no administrado desde el código administrado en Windows 7

Esto ocurre solo después de actualizar a Windows 7, no ocurre en Vista, pero si uso una versión de la DLL nativa compilada en Vista, ¡no cambia nada!
¡Si ejecuto el mismo código de C++ directamente, sin el interoperabilidad administrado, no hay pérdida de memoria!
Si ejecuto el proceso administrado, pero dentro del proceso vshost, ¡no hay pérdida de memoria!

Aquí está la firma llamada:

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

y el nativo de uno:

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

Cuando llamo desde C++, lo llamo así:

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

Cuando mira los contadores de rendimiento para la memoria administrada y no administrada, veo que toda la memoria proviene del código no administrado.
Teniendo en cuenta que el cálculo de referencias es bastante simple, no entiendo por qué hay una diferencia entre llamar a C++ directamente o mediante C#.
Tampoco sé por qué esto sucedería solo en Windows 7 (ambas instalaciones de Windows tenían .net 3.5 SP1).

¿Alguien tiene una idea de cuál es el motivo para esto?

Además, si alguien sabe de una herramienta nativa de creación de perfiles de memoria que funciona en Windows 7, me gustaría saber (por ahora acabo de imprimir para consolar todas las asignaciones explícitas de memoria y no hay diferencias).

+0

LeakDiag [http://mcfunley.com/277/using-leakdiag-to-debug-unmanaged-memory-leaks] o AutomatedQA's AQTime puede hacer un análisis de fugas no administrado. –

+0

¿Qué contador de rendimiento usa para medir el consumo de memoria? –

+0

Ha etiquetado la pregunta "vshost.exe". ¿La aplicación se ejecuta en Visual Studio cuando se mide el consumo de memoria? –

Respuesta

5

Estoy seguro de que el problema está relacionado con la clasificación de los tipos de datos C# en sus contrapartes de C++. Ya que está ordenando el valor de retorno bool a un valor de 1 byte firmado, ¿quizás debería hacer lo mismo con los argumentos de la función? El tipo de bobina de C# es de 4 bytes, ¿tal vez está goteando allí?

Además, especificar el tipo no administrado para las cadenas puede ayudar.

[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 explicación para la commentor:

For the C++ bool type:

En general, un valor cero o nulo-puntero se convierte en falsa, cualquier otro valor se convierte en verdadera.

...

El C++ biblioteca estándar de 1998 define una especialización de la plantilla de vector para bool. La descripción de la clase indica que la implementación debe contener los elementos para que cada bool solo use un bit de memoria.

Así que, casi cualquier valor que use, obtendrá un C++ booleano con el valor verdadero o falso.

+0

Si el bool no coincide en tamaño, no sería una pérdida de memoria, sino más bien una infracción de acceso , o algún tipo de corrupción de la pila. – user7116

+0

buen archivo scott, C# marshals bools como 4bytes. El atributo marshalas faltaba para v y w. http://blogs.msdn.com/oldnewthing/archive/2009/08/13/9867383.aspx –

+0

err. significaba 'encontrar' –

2

Lamentablemente, una vez que involucra cadenas, ninguna clasificación es simple.

Vamos a necesitar más datos para ayudarlo a encontrar este problema. ¿Puede proporcionar la siguiente firma

  • Método Nativo
  • ¿Cómo es la memoria para las cadenas lograron en código nativo?
  • ¿Quizás la muestra de C++ donde usa la API?

EDITAR

intente lo siguiente firma. Esto le dice al CLR no reunir la memoria en ambas direcciones y por tanto solo pasar los datos en.

[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

gracias, pregunta actualizada, las cadenas pasadas son constantes. –

+0

[In] no ayudó, ¿por qué cambiaría entre Vista y Windows 7? también, no mencioné que llamo a este método solo una vez. –

1

me encontré con el uso del útil CLR Profiler al encontrar mi pérdida de memoria.

0

¿Estás seguro de que hay una pérdida de memoria?

¿Cuál es su base para determinar la pérdida de memoria. Usted dice que puede verlo desde los contadores de rendimiento, pero ¿qué observa realmente?¿Ves una curva coninoidal ascendente, o una que se instala en un nivel alto? Un consumo de memoria alto a menudo se confunde por una pérdida de memoria.

btw. ¿Puedes publicar tu definición de función C++ también?

+0

Veo una curva en constante aumento. publiqué la definición de función C++, si me refiero al cuerpo, entonces solo lee datos de un archivo usando ifstream.read –

Cuestiones relacionadas