SqlCeConnection中的访问冲突异常处理 [英] Access Violation Exception in SqlCeConnection dispose

查看:527
本文介绍了SqlCeConnection中的访问冲突异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

应用程序/代码描述



我的应用程序基于c#,并使用SQL Server CE,并且只有两次这种异常在相同的代码位置。这个例外的崩溃没有引入到这个版本。该版本的唯一变化是将.net框架更改为4.5.2。



我在处理时遇到访问冲突异常SqlCeConnection ,并显示以下错误:


尝试读取或写入受保护的内存。这通常是
表示其他内存已损坏的指示。


尝试捕获不会拦截此异常



在我的代码中,我使用以下操作运行

  try 
{
var connectionString = string.Format({0} {1} {2},Data Source =,_localDB, ; File Mode = Read Write; Max Database Size = 4000; Persist Security Info = False;);
使用(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 delete destructor'+ 5c
sqlcese35!Object :: DeleteObjects + 39
sqlcese35!Table ::`vector deleted 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

call st ack for the second crash:

  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

我发现了一些参考提供一些解决方案的网络:


  1. 可能的解决方案:在同一连接上检查多线程问题尝试读写保护内存。这通常表明其他内存已损坏



    拒绝

    a。连接是在使用括号中创建的,不会被重用。

    b。调用方法每5分钟调用一次,并通过转储文件进行验证,它不会同时调用。


  2. 可能的解决方案: sql ce版本不匹配( http://blogs.msdn.com/b/sqlservercompact/archive/2009/05/06/troubleshooting-access-violation-exception-while- use-sql-server-compact-database-with-ado-net-provider.aspx



    可能拒绝:我在安装的版本中可以看到是3.5 SP2(3.5.8080.0),并且从转储中的模块可以看到 sqlceme35.dll 系统.Data.SqlServerCe.dll DLL的版本为3.05.8080.0


  3. 可能的解决方案问题如下:
    https://stackoverflow.com/a/20492181/1447518



    可能拒绝:不听起来从统计的角度来说,代码在同一个地方崩溃了两次,尽管在应用程序代码中有另一个地方写入并读取到另一个DB,应用程序没有崩溃。


  4. 最后一件事我可能会建议DLL的卸载问题(请看第二个调用堆栈)。我的猜测是,应用程序需要它们才能处理该DLL,但是它接缝有点模糊和长射


我的问题是:可能会导致问题,什么是可能的解决方案?

解决方案

虽然此解决方案尚未得到验证,解决方案如下:



从第二个调用堆栈,我可以看到有卸载本机DLL,我猜测SQL连接的dispose方法正在使用当前处理的一种方法。
我验证过程转储,所有的SqlCeConnection类型都在处理过程中。



看到ErikEj评论让我意识到,如果我会看看在SQL-CE 3.5到4.0(System.Data.SqlServerCe.dll)之间的代码差异。



在查看代码后,我可以看到发布的方法被移动到dispose方法中的较后位置。



另外我可以看到,在调用SafeRelease之前,还有一个检查是否检查本机为安全释放而需要的DLL已经被释放了,并抛出一个异常。



底线,SQL-CE 4.0有两个解决方案相同的问题。

我的猜测是这个问题是由于这个原因造成的。



现在的解决方案是在所有应用程序生命周期(没有连接字符串),这导致指针池保留本机Dll e内存用于所有应用程序的生命周期。



更好的解决方案是迁移到SQL-CE 4.0。


Application/Code description:

My application is based on c# and uses SQL Server CE and iv'e got this exception only twice at the same code location. the crash with this exception was not introduced till this version. the only change in this version was changing the .net framework to 4.5.2.

I'm getting access violation exception on the dispose of an SqlCeConnection with the following error:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

This exception is not intercepted by the try catch clause of .net- it causes a crash.

In my code I use the following to run

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);
}

call stack for the first crash:

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 

call stack for the second crash:

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 

I found some references on the internet that suggests some solutions:

  1. Probable solution: check multithreading issue on the same connection (attempted to read write protected memory. this is often an indication that other memory is corrupt)

    Rejection:
    a. the connection is created in the using brackets and doesn't get reused.
    b. the calling method is called every 5 minutes and verified via the dump file that it was not called simultaneously.

  2. Probable solution: sql ce version mismatch (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)

    Probable Rejection: I can see in the version installed is 3.5 SP2 (3.5.8080.0) and from the modules located in the dump I can see the sqlceme35.dll, System.Data.SqlServerCe.dll DLL's are with version 3.05.8080.0

  3. Probable solution which is in question is the following: https://stackoverflow.com/a/20492181/1447518

    Probable Rejection: it doesn't sound right from a statistical perspective- the code crashed twice in the same place although there another place in the application code which writes and read to a different DB and the application didn't crash there.

  4. The last thing I was thinking about, may suggest a unload problem of DLLs (take a look at the second call stack). My guess is that the dll's are unloaded from the application while the application needed them in order to do a dispose, but it seams a bit blurry and a 'long shot'

My question is: what may cause the problem, and what is a probable solution?

解决方案

Although this solution is not yet verified, the solution is as follows:

From the second call stack i can see there is unload of native DLL's, my guess was that the dispose method of the SQL connection was using one of the methods it currently disposed. I verified thorough the Process dump that all the SqlCeConnection types were in the process of dispose.

Seeing ErikEj comment made me realize it's will be better if i will take a look in the code differences that was made between SQL-CE 3.5 to 4.0 (System.Data.SqlServerCe.dll).

after viewing the code, i could see that the method of the release was moved to a later position inside the dispose method.

In addition i could see that before calling SafeRelease there was another check that checks if the native DLLs that were needed for safe release was released already- and throw an exception.

bottom line, SQL-CE 4.0 has 2 solutions for the same issue.

my guess is that this issue was caused because of this.

the solution for now was to keep a connection during all the application life-cycle (which has no connection string), this cause the pointer pool to keep the native Dlls in the memory for all the application life-cycle.

the better solution is to move to SQL-CE 4.0 .

这篇关于SqlCeConnection中的访问冲突异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆