В моем решении есть неуправляемая C++ DLL, которая экспортирует функцию, и управляемое приложение, которое PInvokes эту функцию.
Я только что преобразовал решение из .NET 3.5 в .NET 4.0 и получил исключение PInvokeStackImbalance "Вызов функции PInvoke [...] привел к дисбалансу стека". Как оказалось, я вызывал функцию __cdecl'ed, так как это было __stdcall:
Часть С++ (вызываемый):
__declspec(dllexport) double TestFunction(int param1, int param2); // by default is __cdecl
Часть С# (вызывающий):
[DllImport("TestLib.dll")] // by default is CallingConvention.StdCall
private static extern double TestFunction(int param1, int param2);
Итак, я исправил ошибку, но теперь мне интересно, как это работало в .NET 3.5? Почему (многократно повторяющаяся) ситуация, когда никто (ни callee, ни caller) не очищает стек, не вызывала переполнения стека или каких-либо других нарушений, а просто работала нормально? Есть ли какая-то проверка в PInvoke, как упоминал Рэймонд Чен в его статья? Также интересно, почему противоположный тип нарушения соглашения (когда __stdcall вызывается PInvoked как __cdecl) вообще не работает, вызывая только EntryPointNotFoundException.