2009-10-01 1 views
7

Когда я вызываю неуправляемый код на C++ из моего кода на C#, у меня, похоже, есть какая-то утечка памяти.
C++ читает данные из файла, используя ifstream.read, и записывает его в вектор.утечка памяти при вызове неуправляемого кода из управляемого кода в Windows 7

Это происходит только после обновления до Windows 7, не происходит в Vista, но если я использую версию родной DLL, которая была скомпилирована в Vista, это ничего не меняет!
Если я запускаю тот же код на C++ напрямую, без управляемого взаимодействия, утечки памяти нет!
Если я запускаю управляемый процесс, но внутри процесса vshost утечки памяти нет!

Вот вызов подписи:

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

и родным:

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

Когда я называю это из C++, я называю это так:

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

Когда я посмотрите на счетчики производительности для управляемой и неуправляемой памяти, я вижу, что вся память исходит из неуправляемого кода.
Учитывая, что маршалинг довольно прост, я не понимаю, почему существует разница между вызовом C++ напрямую или через C#.
Я также не знаю, почему это произойдет только в Windows 7 (обе установки Windows имели .net 3.5 SP1).

У кого-нибудь есть идея, в чем причина этого?

Также, если кто-нибудь знает о встроенном профилировании памяти, который работает в Window 7, я был бы рад узнать (на данный момент я только что напечатал для консоли все явное выделение памяти и нет различий).

+0

LeakDiag [http://mcfunley.com/277/using-leakdiag-to-debug-unmanaged-memory-leaks] или AutomatedQA AQTime может выполнять неуправляемый анализ утечки. –

+0

Какой счетчик производительности вы используете для измерения потребления памяти? –

+0

Вы отметили вопрос "vshost.exe". Выполняется ли приложение под Visual Studio при измерении потребления памяти? –

ответ

5

Я уверен, что проблема связана с маршалингом типов данных C# на их части счетчика C++. Поскольку вы маршалируете возвращаемое значение bool на подписанное 1 байтовое значение, возможно, вы должны сделать то же самое с аргументами функции? Тип C# bool - 4 байта, может быть, вы там протекаете?

Также может указывать неуправляемый тип строк.

[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); 

Объяснение для commentor:

For the C++ bool type:

В общем, значение ноль или нуль-указатель превращается в ложь, любое другое значение преобразуется в действительности.

...

1998 C++ Стандартная библиотека определяет специализация вектора шаблона для BOOL. Описание класс указывает, что реализация должна упаковать элементы , так что каждый bool использует только один бит памяти.

Итак, в значительной степени независимо от того, какое значение вы используете, вы получите C++ boolean со значением true или false.

+0

Если bool не соответствует размеру, это не будет утечкой памяти, но, скорее всего, будет нарушено нарушение доступа , или что-то вроде коррупции в стеке. – user7116

+0

хороший файл scott, C# marshals bools как 4bytes. Атрибут marshalas отсутствовал для v и w. http://blogs.msdn.com/oldnewthing/archive/2009/08/13/9867383.aspx –

+0

err. означало «найти» –

2

К сожалению, когда вы включаете строки, сортировка не проста.

Нам понадобятся дополнительные данные, чтобы помочь вам выявить эту проблему. Вы можете предоставить следующие

  • Native Method Подпись
  • Как память для строк удалось в машинный код?
  • Возможно, образец C++, в котором вы используете API?

EDIT

Попробуйте следующую подпись. Это говорит CLR не маршал памяти в обоих направлениях, но вместо того, чтобы только передать данные в системе.

[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

спасибо, обновленный вопрос, переданные строки являются константами. –

+0

[In] не помогло, почему это изменилось между Vista и Windows 7? также, я не упоминал, что я называю этот метод только один раз. –

1

Я нашел использование CLR Profiler полезно при поиске моей утечки памяти.

0

Уверены, что есть утечка памяти?

В чем заключается причина определения утечки памяти. Вы говорите, что можете видеть это из счетчиков производительности, но что вы на самом деле наблюдаете?Вы видите конически растущую кривую, или ту, которая оседает на высоком уровне? Высокое потребление памяти часто путают для утечки памяти.

кстати. Можете ли вы опубликовать также определение функции C++?

+0

Я вижу непрерывно растущую кривую. Я опубликовал определение функции C++, если вы имеете в виду тело, то он просто считывает данные из файла, используя ifstream.read –