pinvokestackimbalance - как это исправить или отключить? - PullRequest
68 голосов
/ 18 августа 2010

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

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

Например, вот подпись C #:

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

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

#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?

Ответы [ 5 ]

130 голосов
/ 18 августа 2010

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

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

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

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

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

37 голосов
/ 12 марта 2012

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

  1. CTRL + ALT + E
  2. В разделе «Помощники по управляемой отладке» снимите флажок PInvokeStackImbalance.
8 голосов
/ 04 сентября 2014

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

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

Скачайте и установите его, закройте Visual Studio и откройте снова, вы можете найти расширение в строке меню. enter image description here

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

Новое окно появится, как показано ниже enter image description here

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

Используйте эту подпись, и вам необходимо изменить ваши программы в соответствии с этой подписью, в основном типом данных.

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

Удачного кодирования Будь здоров!

3 голосов
/ 01 марта 2011

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

Не думайте, что с вашими Dlls что-то не так,нет.

Измените настройки VS, чтобы сгенерировать код X86, подобный этому (Express-версии C #)

  1. , перейдите в Инструменты -> Параметры.
  2. В левом нижнем углу диалогового окна «Параметры» установите флажок «Показать все настройки».
  3. В древовидном представлении слева выберите «Проекты и решения».
  4. В опциях справа установите флажок «Показать расширенные конфигурации сборки».
  5. Нажмите «ОК».
  6. Перейдите в «Сборка» -> Configuration Manager ...
  7. В столбце «Платформа» рядом с вашим проектом щелкните комбинированный список и выберите «».
  8. В настройке «Новая платформа» выберите «x86».
  9. Нажмите кнопку «ОК»..
  10. Нажмите Закрыть.

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

0 голосов
/ 09 мая 2016

Я пытался вызвать dll с CallingConvention, это 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...