近日在测试服务器调试程序时,偶尔会出现以下错误:
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驱动程序进行连接数据库的。