2015-08-31 24 views
6

Applicazione Descrizione/Codice:violazione di accesso Eccezione in SqlCeConnection smaltire

La mia domanda è basata su C# e utilizza SQL Server CE e iv'e ottenuto questa eccezione solo due volte nella stessa posizione del codice. il crash con questa eccezione non è stato introdotto fino a questa versione. l'unica modifica in questa versione stava cambiando il framework .net in 4.5.2.

che sto ricevendo eccezione di violazione di accesso sulla disporre di un SqlCeConnection con il seguente errore:

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

Questa eccezione non viene intercettata dalla clausola try pescato del .net - provoca un crash.

Nel mio codice Io uso il seguente per eseguire

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

stack di chiamate per la prima caduta:

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 

stack di chiamate per il secondo incidente:

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 

ho trovato alcuni riferimenti su Internet che suggeriscono alcune soluzioni:

  1. Probabile soluzione: emissione controllo multithreading sulla stessa connessione (attempted to read write protected memory. this is often an indication that other memory is corrupt)

    Rifiuto:
    a. la connessione viene creata tra parentesi e non viene riutilizzata.
    b. il metodo di chiamata viene chiamato ogni 5 minuti e verificato tramite il file di dump che non è stato chiamato simultaneamente.

  2. Probabile soluzione: SQL Versione ce disadattamento (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)

    Rifiuto supposto: posso vedere nella versione installata è 3.5 SP2 (3.5.8080.0) e dai moduli ubicata nella discarica I può vedere il sqlceme35.dll, System.Data.SqlServerCe.dll DLL sono con la versione 3.05.8080.0

  3. probabile soluzione che è in questione è la seguente: https://stackoverflow.com/a/20492181/1447518

    Rifiuto Probabile: non suona destra da un statistico perspective- il codice caduto due volte nello stesso posto, anche se c'è un altro posto nel codice dell'applicazione, che scrive e leggere a un diverso DB e l'applicazione didn' t crash lì.

  4. L'ultima cosa a cui stavo pensando potrebbe suggerire un problema di scaricamento di DLL (date un'occhiata al secondo stack di chiamate).La mia ipotesi è che le DLL vengono scaricati dall'applicazione mentre l'applicazione li necessaria al fine di fare un dispose, ma cuciture un po 'sfocata e un 'campo lungo'

La mia domanda è: cosa accada causare il problema, e qual è una soluzione probabile?

+0

Si prova a condividere il DB SQL CE? Ad esempio, più utenti (processi) accedono al db su un percorso condiviso? –

+0

Vorrei provare a segnalarlo a M $ connect - connect.microsoft.com. –

+0

C Sharper: no, il DB non è condiviso tra i processi, solo il processo dell'applicazione lo sta accedendo. – Idan

risposta

1

Anche se questa soluzione non è ancora verificato, la soluzione è la seguente:

Dal secondo stack di chiamate posso vedere non v'è lo scarico della nativa DLL, la mia ipotesi è che il metodo Dispose della connessione SQL stava usando uno dei metodi attualmente disposti. Ho verificato accuratamente il dump del processo in cui tutti i tipi SqlCeConnection erano in via di dismissione.

Vedere il commento di ErikEj mi ha fatto capire che sarà meglio se darò un'occhiata alle differenze di codice tra SQL-CE 3.5 e 4.0 (System.Data.SqlServerCe.dll).

dopo aver visto il codice, ho potuto vedere che il metodo del rilascio è stato spostato in una posizione successiva all'interno del metodo di smaltimento.

Inoltre, ho notato che prima di chiamare SafeRelease c'era un altro controllo che verifica se le DLL native necessarie per il rilascio sicuro erano già state rilasciate e lanciavano un'eccezione.

linea di fondo, SQL-CE 4.0 ha 2 soluzioni per lo stesso problema.

la mia ipotesi è che questo problema è stato causato a causa di questo.

la soluzione per ora è stato quello di mantenere un collegamento durante tutto il ciclo di vita dell'applicazione (che non ha stringa di connessione), questa causa il pool puntatore per mantenere le DLL native nella memoria per tutta la vita-ciclo di applicazione.

la soluzione migliore è passare a SQL-CE 4.0.

+1

cuciture come ha risolto il problema – Idan