带有来自 IIS 的 dllimport 的 stackoverflow

stackoverflow with dllimport from IIS

场景

我为 C dll 制作了一个包装器 class,这样我就可以从托管代码调用它的函数,并且可以从 c# WCF 服务访问它们。一切似乎都很好,但是在 C 库中分配大量内存时。 IIS 似乎不喜欢它。它会给我一个 Whosebug 异常。

问题

在 C dll 中分配内存时。它在 IIS 中中断。

char    stmt[163840+1]; // allocation a lot of memory
char    stmt2[163840+1]; // allocation a lot of memory

IIS 是否有特殊设置允许从 C 模块分配更多内存?

公开 C dll 函数的代码

步骤:

 1. use SetDllDirectory
 2. LoadLibrary
 3. then call my function with DLLImport
 4. FreeLibrary

NativeClassWrapper 代码(简化版)

[SuppressUnmanagedCodeSecurity]
public static class NativeClassWrapper
{
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr LoadLibrary(string hModule);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool FreeLibrary(IntPtr hModule);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool SetDllDirectory(string lpPathName);

    [DllImport("myCDll.dll", EntryPoint = "MyFunction", ExactSpelling = false, SetLastError = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
    public static extern int MyFunction(
    );
}

C代码

long MyFunction () {
    char    stmt[163840+1]; // allocation alot of memory
    char    stmt2[163840+1];
    long lReturn = 0L;
    *stmt = '[=13=]';
    *stmt2 = '[=13=]';
    return lReturn;
}
char    stmt[163840+1]; // allocation alot of memory
char    stmt2[163840+1];

这些分配是造成堆栈溢出的原因。您正试图在堆栈上分配大型数组,但堆栈不够大。 Windows 应用程序的默认堆栈为 1MB。数组本身不会溢出这样的堆栈。但是,很可能 IIS 使用较小的堆栈,或者没有您未显示的代码进行类似的大堆栈分配。

如果您真的需要分配这么大的数组,您应该在堆上分配。

感谢 David Heffernan 的回复。我接受他的回答,因为它帮助我找到了这个解决方案。我选择的解决方案是在不同的线程上启动与 C Dll 通信的进程,并将堆栈大小分配为 1MB 而不是默认的 256KB

public void StartNewThread()
{
    const int stacksize = 1024*1024; // 1MB
    var thread = new Thread(NativeDllProcess, stacksize);
    thread.Start();
    thread.Join(); // Wait till thread is ready

    // .. rest of code here
}

private void NativeDllProcess(object info)
{
    // ..... Code thats calls C dll functions
}

更多信息在这里: maximum / default stack size IIS

默认情况下,在本机 IIS 进程中创建的线程的最大堆栈大小为 256 KB  电子邮件  打印 概括 默认情况下,在 Windows Server 2008 之前,由本机 Microsoft Internet 信息服务 (IIS) 进程创建的线程的最大堆栈大小为 256 KB。例如,当 Inetinfo.exe、DLLHost.exe, 或者 W3wp.exe 在 IIS 5.0 或 IIS 6.0 中创建线程,线程的最大堆栈大小默认为 256 KB。您还可以显式调用 CreateThread 函数来指定线程的堆栈大小。在Microsoft Windows 2000 中,如果Microsoft ASP.NET Worker Process (ASPNet_wp.exe) 创建一个线程,则该线程的最大堆栈大小为1 MB。在 Windows Server 2008 及更高版本中,线程的最大堆栈大小 运行 在 32 位版本的 IIS 上为 256 KB,在 x64 服务器上为 512 KB。

注意:Internet Information Services 是一个多线程 Web 应用程序平台,它允许每个工作进程内的应用程序代码 运行 根据需要同时使用数百个或更多线程。每个线程都受相同堆栈大小限制的约束,以便将进程的虚拟内存使用量保持在可管理的限制范围内。