在windows server 2008上,.net 应用程序调用c++ dll时会发生崩溃
来源:互联网 发布:rtx mac 2009 编辑:程序博客网 时间:2024/05/26 05:52
本文来自http://blogs.msdn.com/asiatech/default.aspx 上我写的一篇文章:
.NET application may crash when calling function from native C++ dll
Symptom
===========
Customer built an ASP.NET web application using Visual Studio 2008 on Windows 2008. In the source code, it called a function which was imported from native c++ dll:
[The source code looks like below]
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[System.Runtime.InteropServices.DllImport("PinvokeLib.dll", EntryPoint = " TestStringAsResult", CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
public static extern string TestStringAsResult();
……
protected void Button_Click(object sender, EventArgs e)
{
string str = TestStringAsResult();
}
}
Above code seems working fine during debugging when "Use Visual Studio Development Server" in Web properties. However, when choose the web properties to “Use IIS Web Server”, the web page seems hang and returns server internal error message. This issue will not occur on Windows 2003.
Troubleshoot
===========
We got the source code of native c++ dll and the related method was written like below:
extern "C" PINVOKELIB_API char * TestStringAsResult()
{
return "Test String";
}
We rebuilt the native dll and web application with VS 2008 on a test Windows 2008 server. When we ran the web application, w3wp.exe crashed and WerFault.exe (Windows Error Reporting service) showed up trying to record logs. In the application event log, we found 0xc0000374 exception:
Log Name: Application
Source: Application Error
Date: 12/12/2009 3:37:00 AM
Event ID: 1000
Task Category: (100)
Level: Error
Keywords: Classic
User: N/A
Computer: 182462M
Description:
Faulting application w3wp.exe, version 7.0.6001.18000, time stamp 0x47919413, faulting module ntdll.dll, version 6.0.6001.18000, time stamp 0x4791a7a6, exception code 0xc0000374, fault offset 0x000b015d, process id 0x10e0, application start time 0x01ca7b1f684ff683.
0xc0000374 indicates that there is heap corruption issue existed. We used DebugDiag to catch w3wp.exe crash dump file and found below call stack:
0:023> kL200
ChildEBP RetAddr
052deaf4 77df0d68 ntdll!RtlReportCriticalFailure+0x5b
052deb04 77df0e56 ntdll!RtlpReportHeapFailure+0x21
052deb38 77db0531 ntdll!RtlpLogHeapFailure+0xa1
052deb64 7680c56f ntdll!RtlFreeHeap+0x60
052deb78 77c3dc2c kernel32!HeapFree+0x14
052deb8c 77c3dc53 ole32!CRetailMalloc_Free+0x1c
052deb9c 7a0dce06 ole32!CoTaskMemFree+0x13
052debac 7a0e06c2 mscorwks!DefaultMarshalOverrides<CSTRMarshalerBase>::ReturnCLRFromNative+0x35
052dede8 79e957c3 mscorwks!RunML+0x949
052dee68 79e956b7 mscorwks!NDirectGenericStubPostCall+0x194
052deef4 79e85686 mscorwks!NDirectGenericStubReturnFromCall+0x1f
052deefc 051f0678 mscorwks!NDirectSlimStubWorker2+0x13d
WARNING: Frame IP not in any known module. Following frames may be wrong.
052def38 04836dee 0x51f0678
052def50 04836fdc System_Web_ni+0x276dee
00000000 00000000 System_Web_ni+0x276fdc
0:023> !clrstack
OS Thread Id: 0xb4c (23)
ESP EIP
052def14 77df015d [NDirectMethodFrameGeneric: 052def14] WebApplication3._Default.__PBExternal_fnreturnenstra()
052def24 051f0678 WebApplication3._Default.Button1_Click(System.Object, System.EventArgs)
052def44 04836dee System.Web.UI.WebControls.Button.OnClick(System.EventArgs)
052def58 04836fdc System.Web.UI.WebControls.Button.RaisePostBackEvent(System.String)
……
052df2ec 04663072 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest)
052df2f8 0466157b System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32)
We could see that CoTaskMemFree was called to free unmanaged memory in this situation. The problem is due to CLR use different protocol to allocate memory and free memory between managed code and unmanaged code. According to below MSDN article, when CLR marshals unmanaged memory to the string, it will always invoke CoTaskMemFree method to free the unmanaged memory:
“Memory Management with the Interop Marshaler”
<http://msdn.microsoft.com/en-us/library/f1cf4kkz(VS.80).aspx>
Since the unmanaged memory is not allocate by CoTaskMemAlloc, it will crashed by
ntdll!RtlpLowFragHeapFree checking. This issue will also happen if we use NEW or malloc function to allocate memory in C++ dll. Below code will fail as well:
TCHAR* WINAPI TestStringAsResult()
{
TCHAR *ret;
ret = new TCHAR[10];
wcscpy(ret, L"test");
return ret;
}
To fix this problem, we need to explicitly call CoTaskMemAlloc method to allocate memory in native dll:
#include <objbase.h>
……
extern "C" PINVOKELIB_API char * TestStringAsResult()
{
STRSAFE_LPWSTR result = (STRSAFE_LPWSTR)CoTaskMemAlloc( 64 );
StringCchCopy( result, sizeof(result) , (STRSAFE_LPWSTR)"This is return value" );
return (char *) result;
}
If the unmanaged memory is not allocated with the CoTaskMemAlloc method and could not be changed, we must use an IntPtr and free the memory manually using the appropriate method. The declaration in c# should be changed from:
[System.Runtime.InteropServices.DllImport("PinvokeLib.dll", EntryPoint = " TestStringAsResult", CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
public static extern string TestStringAsResult();
To:
[System.Runtime.InteropServices.DllImport("PinvokeLib.dll", EntryPoint = " TestStringAsResult", CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
public static extern IntPtr TestStringAsResult();
Another Question
===========
Why this problem doesn’t happen under Win2003?
It is because that Windows Vista and Win2008 support new heap verification feature.
“HeapEnableTerminationOnCorruption”
<http://msdn.microsoft.com/en-us/library/aa366705.aspx>
It enables the terminate-on-corruption feature. If the heap manager detects an error in any heap used by the process, it calls the Windows Error Reporting service and terminates the process. So the heap corruption issue will be reported by Win2008 or Vista explicitly while Win2003 OS doesn’t report this though the heap corruption indeed exsits.
More Information
===========
Below two articles provides the sample code of calling native c++ dll function within c#:
“Strings Sample”
http://msdn.microsoft.com/en-us/library/e765dyyy(VS.80).aspx
“PinvokeLib.dll”
http://msdn.microsoft.com/en-us/library/as6wyhwt(VS.80).aspx
References
===========
Marshaling between Managed and Unmanaged Code
http://msdn.microsoft.com/en-us/magazine/cc164193.aspx
Default Marshaling for Strings
http://msdn.microsoft.com/en-us/library/s9ts558h(VS.80).aspx
Default Marshaling for Arrays
http://msdn.microsoft.com/en-us/library/z6cfh6e6(VS.80).aspx
Memory Management with the Interop Marshaler
http://msdn.microsoft.com/en-us/library/f1cf4kkz(VS.80).aspx
Regards,
Hanson Wang
- 在windows server 2008上,.net 应用程序调用c++ dll时会发生崩溃
- SQL Server 调用 C#.net 写的Dll
- 在SQL Server中使用CLR调用.net的dll
- Windows.NET Server 应用程序环境
- ASP.NET可以在Windows Server 2008 R2 Server Core上运行
- C#.net 方法调用 应用程序
- 在 Windows Server 2012 上安装 ASP.NET STATE SERVICE
- [科普小短文]在C#中调用C语言函数(静态调用Native DLL,Windows & Microsoft.Net平台)
- 在Windows Server 2008 X64中通过.NET程序调用32位com组件
- 在windows server 2008上安装iis
- 在Windows 7/Server 2008 R2上部署asp.net 1.1程序
- 在Windows Server 2008 R2上部署ASP.NET MVC应用
- asp.net网站部署在云服务器windows server 2008上
- SQL Server 调用C#。net写的Dll ,(分享我的HelloWorld测验)
- SQL Server 调用C#.net写的Dll ,(分享我的HelloWorld测验)
- 在 WINDOWS SERVER 2008 X86 SP2 上安装C++BUILDER 6 SP4
- 在 WINDOWS SERVER 2008 X86 SP2 上安装C++BUILDER 6 SP4
- 在windows Server 2008 R2上安装oracle 12C 出现的问题以及解决方法
- spec文件
- linux块设备分析与使用(转的)
- vtk体绘制-例子
- 描述一个正确的IP地址
- 常见内存泄露及解决方案(转)
- 在windows server 2008上,.net 应用程序调用c++ dll时会发生崩溃
- ASP.NET 调用存储过程访问数据库
- ORACLE外连接小结~
- 坚定要贡献下去
- 性的短暂而致真情永失
- mtk
- 布线之我见
- 综合:2009年Ruby世界回顾
- 基于51系列单片机的简单c语言编程