SqlCeConnection 处理中的访问冲突异常
Access Violation Exception in SqlCeConnection dispose
Application/Code 描述:
我的应用程序基于 c# 并使用 SQL Server CE,而且我在同一代码位置仅两次遇到此异常。直到这个版本才引入此异常的崩溃。此版本中唯一的变化是将 .net 框架更改为 4.5.2。
我在处理 SqlCeConnection
时遇到访问冲突异常,错误如下:
Attempted to read or write protected memory. This is often an
indication that other memory is corrupt.
这个异常没有被.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)
拒绝:
一种。连接是在使用括号中创建的,不会被重复使用。
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),从转储中的模块我可以看到 sqlceme35.dll
, System.Data.SqlServerCe.dll
DLL 的版本为 3.05.8080.0
可能的解决方案如下:
Probable Rejection:从统计的角度来看这听起来不对——代码在同一个地方崩溃了两次,尽管应用程序代码中还有另一个地方写入和读取一个不同的数据库,应用程序没有在那里崩溃。
我最后想到的可能是DLL的卸载问题(看看第二个调用堆栈)。我的猜测是 dll 从应用程序中卸载,而应用程序需要它们来进行处理,但它的接缝有点模糊并且 'long shot'
我的问题是:可能导致问题的原因是什么,可能的解决方案是什么?
虽然这个方案还没有经过验证,但是方案如下:
从第二个调用堆栈中我可以看到本机 DLL 的卸载,我的猜测是 SQL 连接的处理方法正在使用它当前处理的方法之一。
我通过进程转储验证了所有 SqlCeConnection 类型都在处理过程中。
看到 ErikEj 的评论让我意识到如果我看一下 SQL-CE 3.5 到 4.0 (System.Data.SqlServerCe.dll) 之间的代码差异会更好。
查看代码后,我发现release的方法被移到了dispose方法的后面。
此外,我可以看到在调用 SafeRelease 之前还有另一项检查,检查安全发布所需的本机 DLL 是否已经发布 - 并抛出异常。
最重要的是,SQL-CE 4.0 对同一问题有 2 个解决方案。
我猜这个问题是因为这个引起的。
目前的解决方案是在所有应用程序生命周期(没有连接字符串)中保持连接,这会导致指针池在所有应用程序生命周期内将本机 Dll 保留在内存中。
更好的解决方案是迁移到 SQL-CE 4.0。
Application/Code 描述:
我的应用程序基于 c# 并使用 SQL Server CE,而且我在同一代码位置仅两次遇到此异常。直到这个版本才引入此异常的崩溃。此版本中唯一的变化是将 .net 框架更改为 4.5.2。
我在处理 SqlCeConnection
时遇到访问冲突异常,错误如下:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
这个异常没有被.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)
拒绝:
一种。连接是在使用括号中创建的,不会被重复使用。
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),从转储中的模块我可以看到
sqlceme35.dll
,System.Data.SqlServerCe.dll
DLL 的版本为 3.05.8080.0可能的解决方案如下:
Probable Rejection:从统计的角度来看这听起来不对——代码在同一个地方崩溃了两次,尽管应用程序代码中还有另一个地方写入和读取一个不同的数据库,应用程序没有在那里崩溃。
我最后想到的可能是DLL的卸载问题(看看第二个调用堆栈)。我的猜测是 dll 从应用程序中卸载,而应用程序需要它们来进行处理,但它的接缝有点模糊并且 'long shot'
我的问题是:可能导致问题的原因是什么,可能的解决方案是什么?
虽然这个方案还没有经过验证,但是方案如下:
从第二个调用堆栈中我可以看到本机 DLL 的卸载,我的猜测是 SQL 连接的处理方法正在使用它当前处理的方法之一。 我通过进程转储验证了所有 SqlCeConnection 类型都在处理过程中。
看到 ErikEj 的评论让我意识到如果我看一下 SQL-CE 3.5 到 4.0 (System.Data.SqlServerCe.dll) 之间的代码差异会更好。
查看代码后,我发现release的方法被移到了dispose方法的后面。
此外,我可以看到在调用 SafeRelease 之前还有另一项检查,检查安全发布所需的本机 DLL 是否已经发布 - 并抛出异常。
最重要的是,SQL-CE 4.0 对同一问题有 2 个解决方案。
我猜这个问题是因为这个引起的。
目前的解决方案是在所有应用程序生命周期(没有连接字符串)中保持连接,这会导致指针池在所有应用程序生命周期内将本机 Dll 保留在内存中。
更好的解决方案是迁移到 SQL-CE 4.0。