近日在測試伺服器偵錯工具時,偶爾會出現以下錯誤:
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
地區設定識別碼: 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驅動程式進行串連資料庫的。