утечка памяти при вызове неуправляемого кода из управляемого кода в Windows 7 - PullRequest
7 голосов
/ 01 октября 2009

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

Это происходит только после обновления до Windows 7, не происходит в Vista, но если я использую версию родной dll, скомпилированной в Vista, это ничего не изменит!
Если я запускаю тот же самый код C ++ напрямую, без управляемого interope, утечки памяти нет!
Если я запускаю управляемый процесс, но внутри процесса 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).

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

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

Ответы [ 4 ]

5 голосов
/ 05 октября 2009

Я уверен, что проблема связана с маршалингом типов данных 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);

Объяснение для комментатора:

Для типа C ++ bool:

Обычно нулевой или нулевой указатель значение преобразуется в ложь, любой другой значение преобразуется в true.

... *
1016 *

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

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

2 голосов
/ 01 октября 2009

К сожалению, если вы задействуете строки, сортировка не будет простой.

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

  • Подпись родного метода
  • Как память для строк управляется в собственном коде?
  • Возможно, пример 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);
1 голос
/ 05 октября 2009

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

0 голосов
/ 05 октября 2009

Вы уверены, что произошла утечка памяти?

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

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

...