مدیریت AccessViolationException در برنامه‌های دات نت 4 به بعد
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: دو دقیقه

فرض کنید که از یک برنامه‌ی native ویندوز برای تهیه تصاویر سایت‌ها در یک برنامه‌ی وب استفاده می‌کنید و صبح که به سایت سر زده‌اید پیام در دسترس نبودن سایت قابل مشاهده است. مشکل از کجا است؟!

یک مثال ساده

using System;

namespace AccessViolationExceptionSample
{
    class Program
    {
        private static unsafe void AccessViolation()
        {
            byte b = *(byte*)(8762765876);
        }

        static void Main(string[] args)
        {
            try
            {
                AccessViolation();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            Console.WriteLine("Press a key...");
            Console.ReadKey();
        }
    }
}
برنامه‌ی کنسول فوق را پس از فعال سازی Allow unsafe code در قسمت تنظیمات پروژه، کامپایل کرده و سپس آن‌را خارج از VS.NET اجرا کنید. احتمالا انتظار دارید که قسمت catch این کد حداقل اجرا شود و سپس سطر «کلیدی را فشار دهید» ظاهر گردد. اما ... خیر! کل پروسه کرش کرده و هیچ پیام خطایی را دریافت نخواهید کرد. اگر به لاگ‌های ویندوز مراجعه کنید پیام زیر قابل مشاهده است:
 System.AccessViolationException.  Attempted to read or write protected memory.
 This is often an indication that other memory is corrupt.
و این نوع مسایل هنگام کار با کتابخانه‌های C و ++C زیاد ممکن است رخ دهند. نمونه‌ی آن استفاده از WebControl دات نت است یا هر برنامه‌ی native دیگری. در این حالت اگر برنامه‌ی شما یک برنامه‌ی وب باشد، عملا سایت از کار افتاده‌است. به عبارتی پروسه‌ی ویندوزی آن کرش کرده و بلافاصله از طرف ویندوز خاتمه یافته است.


چرا قسمت catch اجرا نشد؟

از دات نت 4 به بعد، زمانیکه دسترسی غیرمجازی به حافظه صورت گیرد، برای مثال دسترسی به یک pointer آزاد شده، استثنای حاصل، توسط برنامه catch نشده و اجازه داده می‌شود تا برنامه کلا کرش کند. به این نوع استثناءها Corrupted State Exceptions یا CSE گفته می‌شود. اگر نیاز به مدیریت آن‌ها توسط برنامه باشد، باید به یکی از دو طریق زیر عمل کرد:
الف) از ویژگی HandleProcessCorruptedStateExceptions بر روی متد فراخوان کتابخانه‌ی native باید استفاده شود. برای مثال در کدهای فوق خواهیم داشت:
   [HandleProcessCorruptedStateExceptions]
  static void Main(string[] args)
  {
ب) و یا فایل کانفیگ برنامه را ویرایش کرده و چند سطر ذیل را به آن اضافه کنید:
 <?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
     <legacyCorruptedStateExceptionsPolicy enabled="true" />
  </runtime>
</configuration>
در این حالت مدیریت اینگونه خطاها در کل برنامه همانند برنامه‌های تا دات نت 3.5 خواهد شد.
  • #
    ‫۱۰ سال و ۸ ماه قبل، چهارشنبه ۱۶ بهمن ۱۳۹۲، ساعت ۲۳:۱۶
    با سلام
    من در فایل کانفیگ یه WPF App ، تغییرات گفته شده را قرار دادم و خطای زیر رو در vs داد
    The type initializer for 'System.Windows.Application' threw an exception. 
    و بیرون از vs اصلا اجرا نشد خیلی نیاز دارم به این مورد ، چون یه پروژه دارم که درست اجرا میشه اما بعضی مواقع برنامه کرش میکنه و نمی‌تونم catch کنم . با تشکر
    • #
      ‫۱۰ سال و ۸ ماه قبل، چهارشنبه ۱۶ بهمن ۱۳۹۲، ساعت ۲۳:۲۹
      - مطلب فوق بیشتر مرتبط است به استثناهای کتابخانه‌های native استفاده شده در برنامه‌های دات نت. برای سایر موارد باید در فایل App.xaml.cs موارد ذیل را بررسی کنید:
          public partial class App
          {
              public App()
              {
                  this.DispatcherUnhandledException += appDispatcherUnhandledException;
                  AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
              }
      + نمونه تنظیم زیر در فایل app.config یک برنامه WPF کار می‌کند (آزمایش شد):
      <?xml version="1.0"?>
      <configuration>
        <startup>
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
        </startup>
        <runtime>
           <legacyCorruptedStateExceptionsPolicy enabled="true" />
        </runtime>
      </configuration>
  • #
    ‫۱۰ سال و ۷ ماه قبل، جمعه ۲ اسفند ۱۳۹۲، ساعت ۱۳:۰۸
    با سلام؛ من یه پروژه با WPF نوشتم اما یه ایراد داره و اونم اینه که مثلا فرم1 رو 20 بار اجرا می‌کنی خطا نمی‌ده اما بار 21 ام برنامه کرش میکنه و اصلا نمیشه catch کرد. متن خطا در Log ویندوز اینه
    Error 01 :
    Application: MyWPFApp.exe
    Framework Version: v4.0.30319
    Description: The process was terminated due to an unhandled exception.
    Exception Info: exception code c0000005, exception address 77D52239
     
    Error 02 :
    Faulting application name: MyWPFApp.exe, version: 1.0.0.0, time stamp: 0x52d550ac
    Faulting module name: ntdll.dll, version: 6.1.7601.17514, time stamp: 0x4ce7b96e
    Exception code: 0xc0000005
    Fault offset: 0x00032239
    Faulting process id: 0xa28
    Faulting application start time: 0x01cf113ae6813d88
    Faulting application path: R:\Source\MyWPFApp\bin\Debug\MyWPFApp.exe
    Faulting module path: C:\Windows\SYSTEM32\ntdll.dll
    Report Id: 460eda62-7d33-11e3-a572-ac220bc99cf8
     
    Information :
    Fault bucket , type 0
    Event Name: APPCRASH
    Response: Not available
    Cab Id: 0
     
    Problem signature:
    P1: MyWPFApp.exe
    P2: 1.0.0.0
    P3: 52d550ac
    P4: ntdll.dll
    P5: 6.1.7601.17514
    P6: 4ce7b96e
    P7: c0000005
    P8: 00032239
    P9:
    P10:
     
    Attached files:
    C:\Users\Administrator\AppData\Local\Temp\WERE9B3.tmp.WERInternalMetadata.xml
    C:\Users\Administrator\AppData\Local\Temp\WER16AC.tmp.appcompat.txt
    C:\Users\Administrator\AppData\Local\Temp\WER18A1.tmp.hdmp
    C:\Users\Administrator\AppData\Local\Temp\WER3BFA.tmp.mdmp
     
    These files may be available here:
    C:\Users\Administrator\AppData\Local\Microsoft\Windows\WER\ReportQueue\AppCrash_MyWPFApp.exe_125fc667a69fcc31c463a5e1b4032657c4ce830_cab_0ac03d3e
     
    Analysis symbol:
    Rechecking for solution: 0
    Report Id: 460eda62-7d33-11e3-a572-ac220bc99cf8
      • #
        ‫۱۰ سال و ۷ ماه قبل، جمعه ۲ اسفند ۱۳۹۲، ساعت ۲۲:۵۵
        با سلام
        از کامپوننت شرکت‌های ثالث استفاده نکردم . آیا راه حل کلی برای پیدا کردن چنین خطاهایی وجود نداره ، اینترنت رو هم سرچ کردم اما کمک زیادی نکرد که بشه فهمید مشکل از چیه و قبل ارسال این پست 2 ساعت تمام آزمایش کردم خطا نداد اما بعضی مواقع این اتفاق می‌افته .
        در ضمن این برنامه WPF App که برای اوتوماسیون اداری نوشته شده و از  EF 6.2 ، قفل سخت افزاری (که بدون قفل هم این ایراد رو می‌ده)
        • #
          ‫۱۰ سال و ۷ ماه قبل، شنبه ۳ اسفند ۱۳۹۲، ساعت ۰۴:۱۶
          مثال WPF ایی که AccessViolation عمدی دارد: WpfApplicationC0000005.zip
          به فایل‌های App.config و App.xaml.cs آن دقت کنید.
          پروژه را کامپایل کرده و خارج از VS.NET اجرا کنید. خطا را نمایش می‌دهد ولی کرش نمی‌کند.
          • #
            ‫۱۰ سال و ۷ ماه قبل، شنبه ۳ اسفند ۱۳۹۲، ساعت ۱۲:۵۱
            با سلام
            من تگ startup رو به صورت زیر نوشته بودم آیا می‌تونه تاثیر داشته باشه
            <startup useLegacyV2RuntimeActivationPolicy="true">
                <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
                <requiredRuntime version="v4.0.20506"/>
            </startup>
            باز تست می‌کنم ببینم چی میشه ، انشاالله که درست بشه . با تشکر
            • #
              ‫۱۰ سال و ۷ ماه قبل، شنبه ۳ اسفند ۱۳۹۲، ساعت ۱۳:۰۰
              تنظیم یاد شده مربوط به تگ runtime است.