2015-08-19 23 views
3

AccessViolationException是在我們的一個服務中拋出的。我們註冊了AppDomain.CurrentDomain.UnhandledException,並且我們得到了低於調用堆棧的事件。該事件在兩秒內在三個不同的線程中被提升了三次,並且具有完全相同的堆棧。所以一切都應該清楚可以信任AccessViolationException的Stacktrace

另一方面 - 在Windows事件日誌中的相關日誌條目根本不顯示堆棧。我們的應用程序也使用非託管庫,我的猜測是這個例外是由於濫用它們(例如oci)而不是顯示的託管堆棧造成的。

我可以相信堆棧報告是導致問題的堆棧 - 或者這只是一個受過教育的猜測嗎?

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 
    at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count) 
    at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count) 
    at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext() 
    at System.Linq.Enumerable.<TakeIterator>d__3a`1.MoveNext() 
    at System.Data.Services.QueryResultInfo.MoveNext() 
    at System.Data.Services.DataService`1.SerializeResponseBody(RequestDescription description, IDataService dataService, IODataResponseMessage responseMessage) 
    at System.Data.Services.DataService`1.HandleRequest() 
    at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody) 
    at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[]) 
    at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) 
    at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) 
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) 
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) 
    at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet) 
    at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext) 
    at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext) 
    at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result) 
    at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) 
    at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) 
    at System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item) 
    at System.Runtime.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread) 
    at System.Runtime.InputQueue`1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread) 
    at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread) 
    at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result) 
    at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result) 
    at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result) 
    at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state) 
    at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync() 
    at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state) 
    at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult) 
    at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult) 
    at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) 
    at System.Net.LazyAsyncResult.Complete(IntPtr userToken) 
    at System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes) 
    at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP) 

這樣一句話:從Windows事件日誌中的異常代碼猜我認爲這是一個「真正的」窗口AccessViolationException(0xc000005),而不是一個throw new AccessViolationException(0xe043452)

+0

當您遇到訪問衝突時,沒有絕對的保證。發生未定義的行爲。根據*發生的方式,您可能會或可能不會獲得可靠的堆棧跟蹤。 – jalf

+0

我建議在不同的進程中移動託管代碼,並通過HTTP使用來自託管進程的REST調用,您可以在非託管代碼中執行日誌記錄,並且如果一切託管在IIS中,IIS可以輕鬆停止並重新啓動工作進程任何原因。 –

回答

2

堆棧跟蹤頂部方法的源代碼是readily available。你可以知道哪些具體的語句是最有可能的崩潰:

keys = new TKey[count]; 

這襯托代碼,你不能在堆棧跟蹤看到,你只能得到託管代碼堆棧幀的轉儲。所以,是的,這是可靠的,而且AVE是處理器拋出的「硬」,它並沒有向你展示所有的東西。

你需要一個崩潰進程的小型轉儲才能看到更多。並不是說這實際上對你有所幫助,當然崩潰的代碼不會對崩潰負責。它也不是那種重複出現的崩潰,對代碼進行小的更改或者處理不同的數據,這很可能是另一個新的操作符調用。

我們的應用程序使用非託管庫以及

這節省了我要解釋一下對於非託管代碼,可能會損壞GC堆。不要指望在下個月左右完成任何事情,對不起。

2

是否的堆棧跟蹤AccessViolationException指示負責訪問衝突的代碼?答案是
它只顯示哪個呼叫檢測到訪問衝突。隨後的調用將失敗,實際上整個應用程序將會因爲AccessViolationException不是catchable by defaultyou should not catch it而死亡。 這意味着內存是由一些(不是詳盡的清單)的損壞:

  • 不好用非託管依賴
  • 不好用的GCHandle的
  • 越野車不安全的代碼

你猜關於可能濫用非託管依賴的問題可能是AccessViolationException的根本原因。

請記住,內存損壞不是確定性的:即使它正在發生,它並不總是被運行時檢測到。

以下代碼是獲取AccessViolationException的方式Console.WriteLine()。但它也可以提高ExecutionEngineException

class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; 
      Thread.CurrentThread.Name = "Main"; 
      ThreadPool.QueueUserWorkItem(Corrupt, Thread.CurrentThread); 
      ThreadPool.QueueUserWorkItem(RunMethod); 
      Console.ReadLine(); 
     } 

     private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) 
     { 
      Console.WriteLine(e.ExceptionObject); 
     } 

     private static void Corrupt(object state) 
     { 
      unsafe 
      { 
       var thread = (Thread)state; 
       fixed (char* str = thread.Name) 
       { 
        char* increment = str; 
        char* decrement = str; 
        while (true) 
        { 
         *(decrement--) = 'f'; 
         *(increment++) = 'b'; 
         Thread.Sleep(10); 
        } 
       } 
      } 
     } 

     [HandleProcessCorruptedStateExceptions ] 
     public static void RunMethod(object state) 
     { 
      try 
      { 
       while (true) 
       { 
        Console.WriteLine("I'm Alive"); 
        Thread.Sleep(5000); 
       } 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
      } 
     } 
    }