Подтвердить что ты не робот

Pinvokestackimbalance - как я могу это исправить или отключить?

Я просто переключился на vs2010 из vs2008. Точное одно и то же решение, за исключением того, что каждый раз каждый вызов в С++ dll дает исключение "pinvokestackimbalance".

Это исключение не запускается в 2008 году. У меня есть полный доступ к dll С++ и вызывающему приложению. Там нет никаких проблем с pinvoke, но эта проблема делает невозможным отладку других проблем; IDE постоянно останавливается, чтобы рассказать мне об этих вещах.

Например, здесь подпись С#:

    [DllImport("ImageOperations.dll")]
    static extern void FasterFunction(
        [MarshalAs(UnmanagedType.LPArray)]ushort[] inImage, //IntPtr inImage, 
        [MarshalAs(UnmanagedType.LPArray)]byte[] outImage, //IntPtr outImage, 
        int inTotalSize, int inWindow, int inLevel);

Вот как это выглядит на стороне С++:

#ifdef OPERATIONS_EXPORTS
#define OPERATIONS_API __declspec(dllexport)
#else
#define OPERATIONS_API __declspec(dllimport)
#endif
extern "C" {


OPERATIONS_API void __cdecl FasterFunction(unsigned short* inArray, 
                                       unsigned char* outRemappedImage,
                                       int inTotalSize, 
                                       int inWindow, int inLevel);

}

Чем отличаются vs2010 и vs2008, которые могут вызвать выброс этих исключений? Должен ли я добавлять другой набор параметров в директиву DllImport?

4b9b3361

Ответ 1

Во-первых, поймите, что код неправильный (и всегда был). "PInvokeStackImbalance" не является исключением как таковым, а управляемым помощником по отладке. Он был отключен по умолчанию в VS2008, но многие люди его не включили, поэтому он по умолчанию включен в VS2010. MDA не запускается в режиме Release, поэтому он не будет запускаться, если вы создадите для выпуска.

В вашем случае соглашение о вызове неверно. DllImport по умолчанию используется CallingConvention.WinApi, что идентично CallingConvention.StdCall для кода рабочего стола x86. Это должно быть CallingConvention.Cdecl.

Это можно сделать, отредактировав строку [DllImport("ImageOperations.dll")] следующим образом:

[DllImport("ImageOperations.dll", CallingConvention = CallingConvention.Cdecl)]

Для получения дополнительной информации см. эту ссылку в MSDN

Ответ 2

Чтобы отключить его:

  • CTRL + ALT + E
  • В разделе "Управляемые помощники по отладке" снимите флажок PInvokeStackImbalance.

Ответ 3

Лучше решить эту проблему, здесь не так сложно, я упомянул некоторые из методов, это может быть так же, как некоторые из моих друзей, упомянутых выше. Я работаю с PCSC приложение Smartcard, которое я провожу около одной недели, злится, многие изменения, наконец, получили решения.

Для меня его работа с PInvoke Extension, которую я установил для VS2010, вы можете скачать здесь здесь http://www.red-gate.com/products/dotnet-development/pinvoke/

Загрузите его и установите, закройте визуальную студию и откройте снова, вы можете найти расширение в строке меню. enter image description here

Если ошибка связана с тем, что подпись не соответствует вам, просто нажмите на PInvoke.net > Insert PInvoke Signatures

Новое окно будет выглядеть следующим образом: enter image description here

Введите имя dll и щелкните по поиску, вы увидите все функции этой DLL в окне результатов поиска. Нажмите на функцию, в которой вы получите подпись для этой конкретной функции.

Используйте эту подпись, и вам нужно изменить свои программы в соответствии с этой Подпиской, В основном тип данных.

Это решает мою проблему, у вас могут быть разные проблемы, такие как callConvention или дополнительные атрибуты, которые необходимо указать при импорте dll.

Счастливое кодирование Будьте здоровы!

Ответ 4

У меня возникла и эта проблема при использовании VS2010. Что это: Visual Studio по умолчанию использует 64-битный код для "любого процессора". Указатели на переменные (например, строки) теперь становятся 64-битными при вызове внешних Dll, где, поскольку все ваши надежные и надежные Dll используют 32-битные указатели.

Не предполагайте, что с вашими DLL что-то не так, нет.

Измените настройки VS для генерации кода X86, как это (Экспресс-версии С#)

  • перейдите в Инструменты → Параметры.
  • В нижнем левом углу диалогового окна "Параметры" установите флажок "Показать все настройки".
  • В дереве с левой стороны выберите "Проекты и решения".
  • В параметрах справа установите флажок "Показать расширенные конфигурации конфигурации".
  • Нажмите "ОК".
  • Перейти к сборке → Configuration Manager...
  • В столбце "Платформа" рядом с вашим проектом щелкните поле со списком и выберите ".
  • В настройке" Новая платформа "выберите" x86".
  • Нажмите "ОК".
  • Нажмите "Закрыть".

Я также замечаю, что даже если компьютеры удваивают мощность каждые 12 месяцев, мой текущий компьютер с 1 гигабайтом оперативной памяти кажется не быстрее, чем мои первые 486 с 4 мегаграммами. Не беспокойтесь об использовании 64-битного кода, это не будет быстрее или лучше, потому что оно построено на огромной громоздкой объектно-ориентированной башне раздувания.

Ответ 5

Я попытался вызвать dll с CallingConvention is ThisCall, и это сработало для меня. Вот мой код, работающий с BLOB MS Sql Server.

[DllImport("sqlncli11.dll", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.ThisCall)]
            private static extern SafeFileHandle OpenSqlFilestream(
                        string FilestreamPath,
                        UInt32 DesiredAccess,
                        UInt32 OpenOptions,
                        byte[] FilestreamTransactionContext,
                        UInt32 FilestreamTransactionContextLength,
                        Int64 AllocationSize);

Больше на: https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention(v=vs.110).aspx