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?
Ответы
Ответ 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