【问题标题】:Opening SQL Server Connection causes: System.AccessViolationException Attempted to read or write protected memory打开 SQL Server 连接导致:System.AccessViolationException Attempted to read or write protected memory
【发布时间】:2021-05-08 05:49:20
【问题描述】:

全部,

环境: 服务器操作系统:Windows Server 2012R2(64位)

服务器硬件:使用虚拟化软件

基于 .net 框架构建的应用程序:4.6.1(编译=任何 CPU),WinForms 应用程序

我有一个连接到 SQL 服务器的应用程序。当应用程序尝试打开 SQL 服务器连接时,我得到 System.AccessViolationException(下面的堆栈跟踪)。这只发生在该服务器上。该应用程序在其他服务器/工作站上运行良好。我已经完成了以下测试 - 请阅读下文(在堆栈跟踪后了解更多信息)。

异常详情:

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


Application: UpdateCenter.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
   at SNINativeMethodWrapper.SNIPacketAllocate(System.Runtime.InteropServices.SafeHandle, IOType, IntPtr ByRef)
   at System.Data.SqlClient.SNIPacket..ctor(System.Runtime.InteropServices.SafeHandle)
   at System.Data.SqlClient.TdsParserStateObject.GetResetWritePacket()
   at System.Data.SqlClient.TdsParserStateObject.WriteSni(Boolean)
   at System.Data.SqlClient.TdsParserStateObject.WritePacket(Byte, Boolean)
   at System.Data.SqlClient.TdsParser.SendPreLoginHandshake(Byte[], Boolean)
   at System.Data.SqlClient.TdsParser.Connect(System.Data.SqlClient.ServerInfo, System.Data.SqlClient.SqlInternalConnectionTds, Boolean, Int64, Boolean, Boolean, Boolean, Boolean, Boolean, System.Data.SqlClient.SqlAuthenticationMethod, Boolean, System.Data.SqlClient.SqlAuthenticationProviderManager)
   at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(System.Data.SqlClient.ServerInfo, System.String, System.Security.SecureString, Boolean, System.Data.ProviderBase.TimeoutTimer, Boolean, Boolean, Boolean)
   at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(System.Data.SqlClient.ServerInfo, System.String, System.Security.SecureString, Boolean, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SqlCredential, System.Data.ProviderBase.TimeoutTimer)
   at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(System.Data.ProviderBase.TimeoutTimer, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SqlCredential, System.String, System.Security.SecureString, Boolean)
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(System.Data.ProviderBase.DbConnectionPoolIdentity, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SqlCredential, System.Object, System.String, System.Security.SecureString, Boolean, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SessionData, System.Data.ProviderBase.DbConnectionPool, System.String, Boolean, System.Data.SqlClient.SqlAuthenticationProviderManager)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(System.Data.Common.DbConnectionOptions, System.Data.Common.DbConnectionPoolKey, System.Object, System.Data.ProviderBase.DbConnectionPool, System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(System.Data.ProviderBase.DbConnectionPool, System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions, System.Data.Common.DbConnectionPoolKey, System.Data.Common.DbConnectionOptions)
   at System.Data.ProviderBase.DbConnectionPool.CreateObject(System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal)
   at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(System.Data.Common.DbConnection, UInt32, Boolean, Boolean, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal ByRef)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(System.Data.Common.DbConnection, System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal ByRef)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(System.Data.Common.DbConnection, System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal, System.Data.ProviderBase.DbConnectionInternal ByRef)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionFactory, System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>, System.Data.Common.DbConnectionOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>)
   at System.Data.SqlClient.SqlConnection.TryOpen(System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>)
   at System.Data.SqlClient.SqlConnection.Open()
   at PrlSystems.ProductUpdateLibrary.Schema.Drivers.MsSql.SqlServerDataLayerDriver.OpenConnection(System.String)
   at PrlSystems.ProductUpdateLibrary.Schema.DataLayerUpdater.TestConnection(PrlSystems.ProductUpdateLibrary.Schema.DataLayerSettings, System.String ByRef)
   at PrlSystems.UpdateCenter.Forms.Wizard.DatabaseConnectionForm.ctlTestDatabaseConnectionWorker_DoWork(System.Object, System.ComponentModel.DoWorkEventArgs)
   at System.ComponentModel.BackgroundWorker.WorkerThreadStart(System.Object)
   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr, System.Object[], System.Object, System.Object[] ByRef)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Messaging.IMessageSink)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

导致此异常的行是:

connection.Open();

所以我决定远程连接并调试应用程序以查看使用的连接字符串(这是完全合法的连接字符串)。接下来,我编写了一个快速而肮脏的控制台应用程序,它使用相同的连接字符串/使用相同的 SQL 连接对象创建一个 SQL 连接,并在同一台服务器上运行它并且它可以工作。

控制台应用和崩溃的应用之间的唯一区别是:

  • 崩溃的应用是 winforms 应用 vs 控制台应用
  • 崩溃的应用程序通过工作线程(使用后台工作线程)执行连接

我不知道是什么导致了这个异常,我什至无法用我的控制台应用程序重现这个异常。 任何帮助将不胜感激。

===================== 更新1(测试结果)=================== ==

  1. 我确实创建了另一个 winforms 应用程序,并运行了为 SQL 服务器连接的代码,它工作正常,...然后我做了 #2

  2. 我编辑了崩溃的应用程序的 Program.cs 并添加了以下几行

     static void Main()
     {
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         // connection that causes access violation exception
         var conn = new SqlConnection();
         conn.ConnectionString = @"Server=.\sqlexpress;Connection Timeout=5;Integrated Security=True";
         conn.Open(); // <= Will get exception after this line executes!
         conn.Close(); 
     }
    

当应用程序运行时,我仍然收到访问冲突异常。这看起来像这个程序被诅咒或列入黑名单!

===================== 更新2(测试结果)=================== ==

所有,我已经将整个应用程序剥离为只有 Program.cs 文件,其中只有几行用于在 Main() 函数中连接到数据库(并且仅引用了几个标准程序集)。不过,当应用程序运行时,我看到了同样的异常。

然后我将它重新编译为 .net 2、3.5 并且成功了! 我切换到 .net 4 或更高版本的那一刻,异常又回来了。您会认为服务器上安装了错误的东西,但为什么其他 .net 4 应用程序运行完全相同的代码?

【问题讨论】:

  • 我查看了那个线程并尝试了winsock重置,没有什么不同。请注意,虽然我的情况可能有点不同,因为控制台应用程序运行良好,但我的 Winform 应用程序做同样的事情会崩溃。
  • 控制台应用程序和winforms之间的DLL差异?
  • 您使用的是哪个框架版本?您是否尝试过任何其他版本
  • 可能不行,但你能写一个 MRE 吗?其他人可以运行以重现该问题吗?另外,您是否使用连接池?我在堆栈跟踪中看到它。

标签: c# .net sql-server database-connection memory-access


【解决方案1】:

全部,

我找到了问题的根本原因: 对于任何面向 .net 4.5 及更高版本的应用程序,VS 中的 Build/Platform 目标下都有一个设置:

“首选 32 位”

默认情况下,当您创建应用程序时,它会被选中。我们的应用程序未选中此设置,导致我们的服务器上出现访问冲突异常。检查该设置是否解决了问题。

虽然,我解决了这个问题......如果我需要使用这个目标框架构建应用程序,我会担心: .net 4.5 > 我的应用 >= .net 4.0

由于对 .net 4.5 以下的任何内容都禁用了此设置,除非我尝试修复服务器并从软件角度确定缺少什么或未正确安装,否则我永远无法解决此问题。之所以出现这个盒子,只是因为我们在其他服务器/工作站上运行了我们的软件,并且运行良好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    相关资源
    最近更新 更多