带有来自 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 应用程序平台,它允许每个工作进程内的应用程序代码 运行 根据需要同时使用数百个或更多线程。每个线程都受相同堆栈大小限制的约束,以便将进程的虚拟内存使用量保持在可管理的限制范围内。
场景
我为 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 应用程序平台,它允许每个工作进程内的应用程序代码 运行 根据需要同时使用数百个或更多线程。每个线程都受相同堆栈大小限制的约束,以便将进程的虚拟内存使用量保持在可管理的限制范围内。