我会尽可能详细地描述我的问题,但如果需要更详细的解释,请告诉我。
为了简化,假设我有 3 个 DLL(实际上我有更多,但我猜这不是很重要):
managed-1.dll
- 托管 DLL(用 C# .NET 4.0 编写) - 处理请求并在某些请求期间调用第二个 DLL 中的非托管代码unmanaged.dll
- 非托管 DLL(用老式 VC++ 6.0 编写) - 执行多个操作,有时调用第三个 DLLmanaged-2.dll
- 托管 DLL(用 CLI/C++ .NET 3.5 编写) - 我的问题的根源
我在 3 种不同的场景中运行我的代码:
我
managed-1.dll
从控制台应用程序调用 - 一切正常我打电话
managed-1.dll
给ASP.NET Development Server
- 一切都很好我打电话
managed-1.dll
来自IIS
- 一切正常,直到managed-1.dll -> unmanaged.dll -> managed-2.dll
涉及整个序列。
在场景 3 中抛出 StackOverflowException。调试器显示不涉及递归。同样很明显,异常发生在以下类型的调用堆栈中:
managed-1.dll::CallUnmanagedCode()
unmanaged.dll::SomeMethod1()
unmanaged.dll::SomeMethod2()
unmanaged.dll::CallManagedCode()
managed-2.dll::CallUnmanagedCode()
!!标有__declspec(dllexport)
并且不使用任何托管类型!managed-2.dll::FailingMethod()
!!使用托管类型;一开始(甚至第一行代码都没有执行)发生异常!
一件更有趣的事情:调试器显示的参数值FailingMethod
与方法调用点中的值不同。
如果有人有任何线索,请指教。
解决方案:问题与托管-非托管无关,而是与IIS 堆栈大小有关。对我来说,使用editbin工具是不可接受的解决方案。所以我的解决方案 - 在调用之前创建新线程unmanaged.dll
并将堆栈设置为 1 MB:
var result = unchecked ((int)0x800000FF);
var thread = new Thread(() => { result = pinvoke_func(); }, 1024 * 1024); // 1MB
thread.Start();
thread.Join();