应用程序/代码说明:
我的应用程序基于C#,使用SQL Server CE,并且在同一代码位置仅出现了两次此异常。这个异常直到这个版本才被引入。这个版本唯一的变化是将.NET Framework更改为4.5.2。
当我对SqlCeConnection
进行dispose时,我会收到访问冲突异常,错误信息如下:
尝试读取或写入受保护的内存。这通常表示其他内存已损坏。
该异常不会被.NET的try catch子句拦截 - 它会导致崩溃。
在我的代码中,我使用以下内容运行:
try
{
var connectionString = string.Format("{0}{1}{2}", "Data Source=", _localDB, ";File Mode=Read Write;Max Database Size=4000;Persist Security Info=False;");
using (var sqlCeConnection = new SqlCeConnection(connectionString))
{
using (var sqlCeCommand = new SqlCeCommand())
{
sqlCeCommand.Connection = sqlCeConnection;
sqlCeCommand.CommandText = "SELECT * FROM Application";
sqlCeConnection.Open();
var result = (string)sqlCeCommand.ExecuteScalar();
isValid = !IsValid(result);
}
}
}
catch (Exception ex)
{
_log.Error("exception", ex);
}
第一次崩溃的调用栈:
ntdll!ZwWaitForMultipleObjects+a
KERNELBASE!WaitForMultipleObjectsEx+e8
kernel32!WaitForMultipleObjectsExImplementation+b3
kernel32!WerpReportFaultInternal+215
kernel32!WerpReportFault+77
kernel32!BasepReportFault+1f
kernel32!UnhandledExceptionFilter+1fc
ntdll! ?? ::FNODOBFM::`string'+2365
ntdll!_C_specific_handler+8c
ntdll!RtlpExecuteHandlerForException+d
ntdll!RtlDispatchException+45a
ntdll!KiUserExceptionDispatcher+2e
sqlcese35!__SafeRelease+c
sqlcese35!Column::`vector deleting destructor'+5c
sqlcese35!Object::DeleteObjects+39
sqlcese35!Table::`vector deleting destructor'+45
sqlcese35!Table::Release+27
sqlcese35!HashTable::~HashTable+2a
sqlcese35!Store::~Store+12b
sqlcese35!Store::Release+2a
sqlceme35!ME_SafeRelease+17
DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr ByRef)+78
[[InlinedCallFrame] (System.Data.SqlServerCe.NativeMethods.SafeRelease)] System.Data.SqlServerCe.NativeMethods.SafeRelease(IntPtrByRef)
System.Data.SqlServerCe.SqlCeConnection.ReleaseNativeInterfaces()+147
System.Data.SqlServerCe.SqlCeConnection.Dispose(Boolean)+f1
System_ni!System.ComponentModel.Component.Dispose()+18
第二次崩溃的调用栈:
ntdll!NtWaitForMultipleObjects+a
KERNELBASE!WaitForMultipleObjectsEx+e8
kernel32!WaitForMultipleObjectsExImplementation+b3
kernel32!WerpReportFaultInternal+215
kernel32!WerpReportFault+77
kernel32!BasepReportFault+1f
kernel32!UnhandledExceptionFilter+1fc
ntdll! ?? ::FNODOBFM::`string'+2335
ntdll!_C_specific_handler+8c
ntdll!RtlpExecuteHandlerForException+d
ntdll!RtlDispatchException+45a
ntdll!KiUserExceptionDispatcher+2e
<Unloaded_sqlcese35.dll>+7c88c
<Unloaded_sqlceqp35.dll>+102790
0x06ccc898
0x06f9efc8
0x1eca8018
0x1f207400
<Unloaded_sqlcese35.dll>+228dc
0x00000004
0x2edff008
0x00000002
0x00000003
0x00000004
<Unloaded_sqlcese35.dll>+3fbd9
0x06ccc898
DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr ByRef)+78
[[InlinedCallFrame] (System.Data.SqlServerCe.NativeMethods.SafeRelease)] System.Data.SqlServerCe.NativeMethods.SafeRelease(IntPtrByRef)
System.Data.SqlServerCe.SqlCeConnection.ReleaseNativeInterfaces()+147
System.Data.SqlServerCe.SqlCeConnection.Dispose(Boolean)+f1
System_ni!System.ComponentModel.Component.Dispose()+1b
我在互联网上找到了一些参考资料,建议采取以下措施解决问题:
可能的解决方案:检查同一连接的多线程问题 (attempted to read write protected memory. this is often an indication that other memory is corrupt)
拒绝:
a. 连接是在using语句块中创建的,不会被重复使用。
b. 调用方法每5分钟执行一次,并通过转储文件验证它没有同时被调用。可能的解决方案:sql ce版本不匹配 (http://blogs.msdn.com/b/sqlservercompact/archive/2009/05/06/troubleshooting-access-violation-exception-while-using-sql-server-compact-database-with-ado-net-provider.aspx)
可能的拒绝:我可以看到安装的版本是3.5 SP2(3.5.8080.0),从dump中定位的模块中可以看到
sqlceme35.dll
,System.Data.SqlServerCe.dll
的版本是3.05.8080.0。可能的解决方案,参考以下链接:https://dev59.com/JHRB5IYBdhLWcg3wiHpl#20492181
可能的拒绝:从统计角度来看,代码在同一位置崩溃了两次,但应用程序中还有另一个写入和读取不同数据库的地方,并且应用程序在那里没有崩溃。
我最后想到的一点是可能存在DLL卸载问题(请查看第二个调用堆栈)。我猜测dll在应用程序需要它们进行dispose时被从应用程序中卸载,但这似乎有些模糊,是一种‘长期射击’
AccessViolationException
或任何其他已损坏的状态异常。这表明出现了严重问题,而且内存已经被破坏。请参见此答案以获取解决方法。(解决方法仅应用于调试,而非生产代码。) - theB