Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

จับ OutOfMemoryException ใน C#

การจับข้อยกเว้น OutOfMemoryException ใน C#

System.OutOfMemoryException เกิดขึ้นเมื่อ CLR ไม่สามารถจัดสรรหน่วยความจำเพียงพอสำหรับอ็อบเจกต์ใหม่ได้ สืบมาจาก System.SystemException

สถานการณ์ตัวอย่าง

การใช้ StringBuilder กำหนด Capacity เท่ากับความยาวเริ่มต้น แล้วพยายาม Insert เพิ่มเติม

ตัวอย่างโค้ดที่ทำให้เกิด Exception


using System;
using System.Text;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string studentName = "Tom";
                string studentSubject = "Maths";
                
                // Capacity = Length = 3, MaxCapacity = 3 (ไม่สามารถขยายได้)
                StringBuilder sb = new StringBuilder(studentName.Length, studentName.Length);
                sb.Append(studentName); // "Tom"
                
                // พยายาม Insert เพิ่ม -> OutOfMemoryException
                sb.Insert(studentSubject, studentName.Length - 1, 1);
            }
            catch (OutOfMemoryException e)
            {
                Console.WriteLine("Error: Out of memory");
                Console.WriteLine(e.Message);
            }
        }
    }
}

ผลลัพธ์


Error: Out of memory
Out of memory

สาเหตุทั่วไปของ OutOfMemoryException

  • สร้างอ็อบเจกต์ขนาดใหญ่เกินไป (Large Object Heap > 85KB)
  • Memory Leak (Event handlers ไม่ Unsubscribe, Static References)
  • StringBuilder กำหนด MaxCapacity ต่ำเกินไป
  • ประมวลผลข้อมูลขนาดใหญ่ใน 32-bit Process (จำกัด 2GB/4GB)

แนวทางแก้ไขและป้องกัน

  1. ใช้ 64-bit Process (Prefer 32-bit = false ใน Project Properties)
  2. หลีกเลี่ยงการเก็บข้อมูลขนาดใหญ่ใน Memory นานๆ (Streaming, Chunking)
  3. ใช้ StringBuilder โดยไม่กำหนด MaxCapacity หรือกำหนดให้พอเพียง
  4. Implement IDisposable และ เรียก Dispose() ให้ถูกต้อง
  5. ใช้ GC.TryStartNoGCRegion สำหรับ Critical Sections (Advanced)

หมายเหตุ

ใน .NET Core / .NET 5+ GC ปรับปรุงแล้ว จัดการ Large Objects ดีกว่า แต่ยังควรเขียนโค้ดให้ Memory Efficient