连接Oracle时出现“System.AccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”错误的问题

    近日在测试服务器调试程序时,偶尔会出现以下错误:

System.AccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
   在 System.Data.Common.UnsafeNativeMethods.OCIEnvCreate(IntPtr& envhpp, MODE mode, IntPtr ctxp, IntPtr malocfp, IntPtr ralocfp, IntPtr mfreefp, UInt32 xtramemsz, IntPtr usrmempp)
   在 System.Data.OracleClient.TracedNativeMethods.OCIEnvCreate(IntPtr& envhpp, MODE mode)
   在 System.Data.OracleClient.OciHandle..ctor(OciHandle parentHandle, HTYPE handleType, MODE ocimode, HANDLEFLAG handleflags)
   在 System.Data.OracleClient.OracleInternalConnection.OpenOnLocalTransaction(String userName, String password, String serverName, Boolean integratedSecurity, Boolean unicode, Boolean omitOracleConnectionName)
   在 System.Data.OracleClient.OracleInternalConnection..ctor(OracleConnectionString connectionOptions)
   在 System.Data.OracleClient.OracleConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
   在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
   在 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
   在 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
   在 System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   在 System.Data.OracleClient.OracleConnection.Open()
   在 RINP.DbUtility.OracleHelper.ExecuteReader(String connectionString, CommandType commandType, String commandText, OracleParameter[] commandParameters)
   在 RINP.DbUtility.DataAccess.ExecuteReader(CommandType commandType, String commandText, OracleParameter[] commandParameters)
   在 RINP.DbUtility.DataAccess.ExecuteReader(String commandText)
   在 RINP.SGPFramework.Caches.MobileLocationMappingCache.Prepare()
   在 RINP.SysFramework.FatCache.CacheBase.BuildCache()
   在 RINP.SysFramework.FatCache.CacheBase..ctor()
   在 RINP.SGPFramework.Caches.MobileLocationMappingCache.get_Current()
   在 RINP.SGPFramework.Rpc.RpcHelper.GetLocationInfoByPhone(String phoneNumber)
   在 RINP.Services.BOSS.SubReceive.ReceiveService.DealReport(MessageHeader header, String provinceCode, String savePath)

     或:

System.AccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
   在 System.Data.Common.UnsafeNativeMethods.OCIEnvCreate(IntPtr& envhpp, MODE mode, IntPtr ctxp, IntPtr malocfp, IntPtr ralocfp, IntPtr mfreefp, UInt32 xtramemsz, IntPtr usrmempp)
   在 System.Data.OracleClient.TracedNativeMethods.OCIEnvCreate(IntPtr& envhpp, MODE mode)
   在 System.Data.OracleClient.OciHandle..ctor(OciHandle parentHandle, HTYPE handleType, MODE ocimode, HANDLEFLAG handleflags)
   在 System.Data.OracleClient.OracleInternalConnection.OpenOnLocalTransaction(String userName, String password, String serverName, Boolean integratedSecurity, Boolean unicode, Boolean omitOracleConnectionName)
   在 System.Data.OracleClient.OracleInternalConnection..ctor(OracleConnectionString connectionOptions)
   在 System.Data.OracleClient.OracleConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
   在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
   在 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
   在 System.Data.ProviderBase.DbConnectionPool.PoolCreateRequest(Object state)
   在 System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)
   在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
   在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)

    或:

Message: $$$$$$$$$$$$$$ Open OracleConnection Failed!.  Exception: System.Exception: OCIEnvCreate 失败,返回代码为 -1,但错误消息文本不可用。
   在 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
   在 System.Data.ProviderBase.DbConnectionPool.PoolCreateRequest(Object state)
   在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   在 System.Data.OracleClient.OracleConnection.Open()
   在 RINP.Services.BOSS.SubReceive.RPCHAComponent.Start()

     windows捕获的出错模块信息为:

描述:
  Stopped working

问题签名:
  问题事件名称:    APPCRASH
  Application Name:    HAWorker_SubReceive.exe
  Application Version:    4.0.0.0
  Application Timestamp:    4e66c549
  Fault Module Name:    ntdll.dll
  Fault Module Version:    6.0.6001.18538
  Fault Module Timestamp:    4cb733e1
  Exception Code:    c0000005
  Exception Offset:    0002a6fd
  OS 版本:    6.0.6001.2.1.0.274.10
  区域设置 ID:    2052

    

     该程序精简后的核心部分非常简单,仅打开一个数据库连接:

using (OracleConnection cn = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.10.110.10)(PORT = 1521)))(CONNECT_DATA=(SERVICE_NAME = UIDB)));user id=core;password=sys;min pool size=1;max pool size=1; enlist=false"))
                {
                    try
                    {
                        Debug.WriteLine("$$$$$$$$$$$$$$ Begin Open OracleConnection.");
                        cn.Open();
                        Debug.WriteLine("$$$$$$$$$$$$$$ Open OracleConnection Success!.");
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(String.Format("$$$$$$$$$$$$$$ Open OracleConnection Failed!.  Exception: {0}", ex.ToString()));
                        Console.ReadLine();
                    }
                }
    
    而在其他服务器并无问题,特定的两台测试服务器确偶尔出现上述异常。经分析,有两个方面的原因促成该问题:
    1. 对应应用程序的其中一个相关Assembly编译发布时误强制指定为“x86”模式,故运行时将以32位运行或wow64模式运行。出现问题的测试服务器均为64位,故运行时在WOW64模式下,将自动寻找32位的Oracle驱动来连接数据库; 
    2. 测试服务器虽同时安装了32位oracle驱动和64位驱动,但32位驱动是直接从网上下载“instantclient-basic-win32”驱动dll并设置Path的方式完成的,经测试该方式下的32位驱动存在一定的问题(64位驱动可按此方式操作)。
 
    解决办法:
    1. 编译assembly时全部采用any cpu模式;
    2. 对于32位的oracle驱动,采取直接安装oracle客户端的方式完成。实际对于用any cpu进行编译的程序,在64位操作系统下将自动使用64位的oracle驱动程序进行连接数据库的。
原文地址:https://www.cnblogs.com/qguohog/p/2174860.html