Bagikan melalui


OutOfMemoryException Kelas

Definisi

Pengecualian yang dilemparkan ketika tidak ada cukup memori untuk melanjutkan eksekusi program.

public ref class OutOfMemoryException : Exception
public ref class OutOfMemoryException : SystemException
public class OutOfMemoryException : Exception
public class OutOfMemoryException : SystemException
[System.Serializable]
public class OutOfMemoryException : SystemException
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class OutOfMemoryException : SystemException
type OutOfMemoryException = class
    inherit Exception
type OutOfMemoryException = class
    inherit SystemException
[<System.Serializable>]
type OutOfMemoryException = class
    inherit SystemException
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type OutOfMemoryException = class
    inherit SystemException
Public Class OutOfMemoryException
Inherits Exception
Public Class OutOfMemoryException
Inherits SystemException
Warisan
OutOfMemoryException
Warisan
OutOfMemoryException
Turunan
Atribut

Keterangan

OutOfMemoryException menggunakan HRESULT COR_E_OUTOFMEMORY, yang memiliki nilai 0x8007000E.

Untuk daftar nilai properti awal untuk instans OutOfMemoryException, lihat OutOfMemoryException konstruktor.

Catatan

Nilai properti yang diwariskan Data selalu null.

Pengecualian OutOfMemoryException memiliki dua penyebab utama:

  • Anda mencoba memperluas StringBuilder objek di luar panjang yang ditentukan oleh propertinya StringBuilder.MaxCapacity .

  • Runtime bahasa umum tidak dapat mengalokasikan memori yang cukup berdampingan untuk berhasil melakukan operasi. Pengecualian ini dapat dilemparkan oleh penetapan properti atau panggilan metode apa pun yang memerlukan alokasi memori. Untuk informasi selengkapnya tentang penyebab OutOfMemoryException pengecualian, lihat posting blog "Kehabisan Memori" Tidak Merujuk ke Memori Fisik.

    Jenis OutOfMemoryException pengecualian ini mewakili kegagalan besar. Jika Anda memilih untuk menangani pengecualian, Anda harus menyertakan catch blok yang memanggil Environment.FailFast metode untuk mengakhiri aplikasi Anda dan menambahkan entri ke log peristiwa sistem, seperti yang dilakukan contoh berikut.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          try {
             // Outer block to handle any unexpected exceptions.
             try {
                string s = "This";
                s = s.Insert(2, "is ");
    
                // Throw an OutOfMemoryException exception.
                throw new OutOfMemoryException();
             }
             catch (ArgumentException) {
                Console.WriteLine("ArgumentException in String.Insert");
             }
    
             // Execute program logic.
          }
          catch (OutOfMemoryException e) {
             Console.WriteLine("Terminating application unexpectedly...");
             Environment.FailFast(String.Format("Out of Memory: {0}",
                                                e.Message));
          }
       }
    }
    // The example displays the following output:
    //        Terminating application unexpectedly...
    
    open System
    
    try
        // Outer block to handle any unexpected exceptions.
        try
            let s = "This"
            let s = s.Insert(2, "is ")
    
            // Throw an OutOfMemoryException exception.
            raise (OutOfMemoryException())
        with
        | :? ArgumentException ->
            printfn "ArgumentException in String.Insert"
    
        // Execute program logic.
    with :? OutOfMemoryException as e ->
        printfn "Terminating application unexpectedly..."
        Environment.FailFast $"Out of Memory: {e.Message}"
    // The example displays the following output:
    //        Terminating application unexpectedly...
    
    Module Example
       Public Sub Main()
          Try
             ' Outer block to handle any unexpected exceptions.
             Try
                Dim s As String = "This"
                s = s.Insert(2, "is ")
    
                ' Throw an OutOfMemoryException exception.
                Throw New OutOfMemoryException()
             Catch e As ArgumentException
                Console.WriteLine("ArgumentException in String.Insert")
             End Try
             
             ' Execute program logic.
    
          Catch e As OutOfMemoryException
             Console.WriteLine("Terminating application unexpectedly...")
             Environment.FailFast(String.Format("Out of Memory: {0}",
                                                e.Message))
          End Try
       End Sub
    End Module
    ' The example displays the following output:
    '       Terminating application unexpectedly...
    

Beberapa kondisi di mana pengecualian dilemparkan dan tindakan yang dapat Anda ambil untuk menghilangkannya termasuk yang berikut ini:

Anda memanggil StringBuilder.Insert metode .

Anda mencoba meningkatkan panjang StringBuilder objek di luar ukuran yang ditentukan oleh propertinya StringBuilder.MaxCapacity . Contoh berikut mengilustrasikan OutOfMemoryException pengecualian yang dilemparkan oleh panggilan ke StringBuilder.Insert(Int32, String, Int32) metode ketika contoh mencoba menyisipkan string yang akan menyebabkan properti objek Length melebihi kapasitas maksimumnya.

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      StringBuilder sb = new StringBuilder(15, 15);
      sb.Append("Substring #1 ");
      try {
         sb.Insert(0, "Substring #2 ", 1);
      }
      catch (OutOfMemoryException e) {
         Console.WriteLine("Out of Memory: {0}", e.Message);
      }
   }
}
// The example displays the following output:
//    Out of Memory: Insufficient memory to continue the execution of the program.
open System
open System.Text

let sb = StringBuilder(15, 15)
sb.Append "Substring #1 "
|> ignore
try
    sb.Insert(0, "Substring #2 ", 1)
    |> ignore
with :? OutOfMemoryException as e ->
    printfn $"Out of Memory: {e.Message}"
// The example displays the following output:
//    Out of Memory: Insufficient memory to continue the execution of the program.
Imports System.Text

Module Example
   Public Sub Main()
      Dim sb As New StringBuilder(15, 15)
      sb.Append("Substring #1 ")
      Try
         sb.Insert(0, "Substring #2 ", 1)
      Catch e As OutOfMemoryException
         Console.WriteLine("Out of Memory: {0}", e.Message)
      End Try
   End Sub
End Module
' The example displays the following output:
'   Out of Memory: Insufficient memory to continue the execution of the program.

Anda dapat melakukan salah satu hal berikut ini untuk mengatasi kesalahan:

Aplikasi Anda berjalan sebagai proses 32-bit.

Proses 32-bit dapat mengalokasikan maksimum 2GB memori mode pengguna virtual pada sistem 32-bit, dan memori mode pengguna virtual 4GB pada sistem 64-bit. Ini dapat membuatnya lebih sulit bagi runtime bahasa umum untuk mengalokasikan memori yang cukup berdada ketika alokasi besar diperlukan. Sebaliknya, proses 64-bit dapat mengalokasikan memori virtual hingga 8 TB. Untuk mengatasi pengecualian ini, kompilasi ulang aplikasi Anda untuk menargetkan platform 64-bit. Untuk informasi tentang menargetkan platform tertentu di Visual Studio, lihat Cara: Mengonfigurasi Proyek ke Platform Target.

Aplikasi Anda membocorkan sumber daya yang tidak dikelola

Meskipun pengumpul sampah dapat membebaskan memori yang dialokasikan untuk jenis terkelola, ia tidak mengelola memori yang dialokasikan untuk sumber daya yang tidak dikelola seperti handel sistem operasi (termasuk handel ke file, file yang dipetakan memori, pipa, kunci registri, dan handel tunggu) dan blok memori yang dialokasikan langsung oleh panggilan Windows API atau oleh panggilan ke fungsi alokasi memori seperti malloc. Jenis yang menggunakan sumber daya yang tidak dikelola mengimplementasikan IDisposable antarmuka.

Jika Anda menggunakan jenis yang menggunakan sumber daya yang tidak dikelola, Anda harus yakin untuk memanggil metodenya IDisposable.Dispose ketika Anda telah selesai menggunakannya. (Beberapa jenis juga mengimplementasikan Close metode yang identik dalam fungsi dengan Dispose metode.) Untuk informasi selengkapnya, lihat topik Menggunakan Objek yang Mengimplementasikan IDisposable .

Jika Anda telah membuat jenis yang menggunakan sumber daya yang tidak dikelola, pastikan Anda telah menerapkan pola Buang dan, jika perlu, menyediakan finalizer. Untuk informasi selengkapnya, lihat Menerapkan metode Buang dan Object.Finalize.

Anda mencoba membuat array besar dalam proses 64-bit

Secara default, runtime bahasa umum dalam .NET Framework tidak mengizinkan objek tunggal yang ukurannya melebihi 2GB. Untuk mengambil alih default ini, Anda dapat menggunakan <pengaturan file konfigurasi gcAllowVeryLargeObjects> untuk mengaktifkan array yang ukuran totalnya melebihi 2 GB. Pada .NET Core, dukungan untuk array yang lebih besar dari 2 GB diaktifkan secara default.

Anda bekerja dengan kumpulan data yang sangat besar (seperti array, koleksi, atau himpunan data database) dalam memori.

Ketika struktur data atau himpunan data yang berada dalam memori menjadi sangat besar sehingga runtime bahasa umum tidak dapat mengalokasikan memori yang cukup berdampingan untuknya, hasil OutOfMemoryException pengecualian.

Untuk mencegah OutOfMemoryException pengecualian, Anda harus memodifikasi aplikasi Anda sehingga lebih sedikit data yang disimpan dalam memori, atau data dibagi menjadi segmen yang memerlukan alokasi memori yang lebih kecil. Contohnya:

  • Jika Anda mengambil semua data dari database lalu memfilternya di aplikasi untuk meminimalkan perjalanan ke server, Anda harus memodifikasi kueri untuk mengembalikan hanya subset data yang dibutuhkan aplikasi Anda. Saat bekerja dengan tabel besar, beberapa kueri hampir selalu lebih efisien daripada mengambil semua data dalam satu tabel lalu memanipulasinya.

  • Jika Anda menjalankan kueri yang dibuat pengguna secara dinamis, Anda harus memastikan bahwa jumlah rekaman yang dikembalikan oleh kueri dibatasi.

  • Jika Anda menggunakan array besar atau objek koleksi lain yang ukurannya menghasilkan OutOfMemoryException pengecualian, Anda harus memodifikasi aplikasi Anda untuk mengerjakan data dalam subset daripada bekerja dengan semuanya sekaligus.

Contoh berikut mendapatkan array yang terdiri dari 200 juta nilai floating-point lalu menghitung nilai rata-ratanya. Output dari contoh menunjukkan bahwa, karena contoh menyimpan seluruh array dalam memori sebelum menghitung rata-rata, dilemparkan OutOfMemoryException .

using System;
using System.Collections.Generic;

public class Example
{
   public static void Main()
   {
      Double[] values = GetData();
      // Compute mean.
      Console.WriteLine("Sample mean: {0}, N = {1}",
                        GetMean(values), values.Length);
   }

   private static Double[] GetData()
   {
      Random rnd = new Random();
      List<Double> values = new List<Double>();
      for (int ctr = 1; ctr <= 200000000; ctr++) {
         values.Add(rnd.NextDouble());
         if (ctr % 10000000 == 0)
            Console.WriteLine("Retrieved {0:N0} items of data.",
                              ctr);
      }
      return values.ToArray();
   }

   private static Double GetMean(Double[] values)
   {
      Double sum = 0;
      foreach (var value in values)
         sum += value;

      return sum / values.Length;
   }
}
// The example displays output like the following:
//    Retrieved 10,000,000 items of data.
//    Retrieved 20,000,000 items of data.
//    Retrieved 30,000,000 items of data.
//    Retrieved 40,000,000 items of data.
//    Retrieved 50,000,000 items of data.
//    Retrieved 60,000,000 items of data.
//    Retrieved 70,000,000 items of data.
//    Retrieved 80,000,000 items of data.
//    Retrieved 90,000,000 items of data.
//    Retrieved 100,000,000 items of data.
//    Retrieved 110,000,000 items of data.
//    Retrieved 120,000,000 items of data.
//    Retrieved 130,000,000 items of data.
//
//    Unhandled Exception: OutOfMemoryException.
open System

let getData () =
    let rnd = Random()
    [|  for i = 1 to 200000000 do
            rnd.NextDouble()
            if i % 10000000 = 0 then
                printfn $"Retrieved {i:N0} items of data." |]
    
let getMean values =
    let sum = Array.sum values

    sum / float values.Length

let values = getData ()
// Compute mean.
printfn $"Sample mean: {getMean values}, N = {values.Length}"

// The example displays output like the following:
//    Retrieved 10,000,000 items of data.
//    Retrieved 20,000,000 items of data.
//    Retrieved 30,000,000 items of data.
//    Retrieved 40,000,000 items of data.
//    Retrieved 50,000,000 items of data.
//    Retrieved 60,000,000 items of data.
//    Retrieved 70,000,000 items of data.
//    Retrieved 80,000,000 items of data.
//    Retrieved 90,000,000 items of data.
//    Retrieved 100,000,000 items of data.
//    Retrieved 110,000,000 items of data.
//    Retrieved 120,000,000 items of data.
//    Retrieved 130,000,000 items of data.
//
//    Unhandled Exception: OutOfMemoryException.
Imports System.Collections.Generic

Module Example
   Public Sub Main()
      Dim values() As Double = GetData()
      ' Compute mean.
      Console.WriteLine("Sample mean: {0}, N = {1}",
                        GetMean(values), values.Length)
   End Sub
   
   Private Function GetData() As Double()
      Dim rnd As New Random()
      Dim values As New List(Of Double)()
      For ctr As Integer = 1 To 200000000
         values.Add(rnd.NextDouble)
         If ctr Mod 10000000 = 0 Then
            Console.WriteLine("Retrieved {0:N0} items of data.",
                              ctr)
         End If
      Next
      Return values.ToArray()
   End Function
   
   Private Function GetMean(values() As Double) As Double
      Dim sum As Double = 0
      For Each value In values
         sum += value
      Next
      Return sum / values.Length
   End Function
End Module
' The example displays output like the following:
'    Retrieved 10,000,000 items of data.
'    Retrieved 20,000,000 items of data.
'    Retrieved 30,000,000 items of data.
'    Retrieved 40,000,000 items of data.
'    Retrieved 50,000,000 items of data.
'    Retrieved 60,000,000 items of data.
'    Retrieved 70,000,000 items of data.
'    Retrieved 80,000,000 items of data.
'    Retrieved 90,000,000 items of data.
'    Retrieved 100,000,000 items of data.
'    Retrieved 110,000,000 items of data.
'    Retrieved 120,000,000 items of data.
'    Retrieved 130,000,000 items of data.
'
'    Unhandled Exception: OutOfMemoryException.

Contoh berikut menghilangkan OutOfMemoryException pengecualian dengan memproses data masuk tanpa menyimpan seluruh himpunan data dalam memori, menserialisasikan data ke file jika perlu untuk mengizinkan pemrosesan lebih lanjut (baris ini dikomentari dalam contoh, karena dalam hal ini mereka menghasilkan file yang ukurannya lebih besar dari 1GB), dan mengembalikan rata-rata terhitung dan jumlah kasus ke rutinitas panggilan.

using System;
using System.IO;

public class Example
{
   public static void Main()
   {
      Tuple<Double, long> result = GetResult();
      Console.WriteLine("Sample mean: {0}, N = {1:N0}",
                        result.Item1, result.Item2);
   }

   private static Tuple<Double, long> GetResult()
   {
      int chunkSize = 50000000;
      int nToGet = 200000000;
      Random rnd = new Random();
      // FileStream fs = new FileStream(@".\data.bin", FileMode.Create);
      // BinaryWriter bin = new BinaryWriter(fs);
      // bin.Write((int)0);
      int n = 0;
      Double sum = 0;
      for (int outer = 0;
           outer <= ((int) Math.Ceiling(nToGet * 1.0 / chunkSize) - 1);
           outer++) {
         for (int inner = 0;
              inner <= Math.Min(nToGet - n - 1, chunkSize - 1);
              inner++) {
            Double value = rnd.NextDouble();
            sum += value;
            n++;
            // bin.Write(value);
         }
      }
      // bin.Seek(0, SeekOrigin.Begin);
      // bin.Write(n);
      // bin.Close();
      return new Tuple<Double, long>(sum/n, n);
   }
}
// The example displays output like the following:
//    Sample mean: 0.500022771458399, N = 200,000,000
open System
// open System.IO

let getResult () =
    let chunkSize = 50000000
    let nToGet = 200000000
    let rnd = Random()
    // use fs = new FileStream(@".\data.bin", FileMode.Create)
    // use bin = new BinaryWriter(fs)
    // bin.Write 0
    let mutable n = 0
    let mutable sum = 0.
    for _ = 0 to int (ceil (nToGet / chunkSize |> float) - 1.) do
        for _ = 0 to min (nToGet - n - 1) (chunkSize - 1) do
            let value = rnd.NextDouble()
            sum <- sum + value
            n <- n + 1
            // bin.Write(value)
    // bin.Seek(0, SeekOrigin.Begin) |> ignore
    // bin.Write n
    sum / float n, n

let mean, n = getResult ()
printfn $"Sample mean: {mean}, N = {n:N0}"

// The example displays output like the following:
//    Sample mean: 0.500022771458399, N = 200,000,000
Imports System.IO

Module Example
   Public Sub Main()
      Dim result As Tuple(Of Double, Long) = GetResult()
      Console.WriteLine("Sample mean: {0}, N = {1:N0}",
                        result.Item1, result.Item2)
   End Sub

   Private Function GetResult As Tuple(Of Double, Long)
      Dim chunkSize As Integer = 50000000
      Dim nToGet As Integer = 200000000
      Dim rnd As New Random()
'       Dim fs As New FileStream(".\data.bin", FileMode.Create)
'       Dim bin As New BinaryWriter(fs)
'       bin.Write(CInt(0))
      Dim n As Integer
      Dim sum As Double
      For outer As Integer = 0 To CInt(Math.Ceiling(nToGet/chunkSize) - 1)
         For inner = 0 To Math.Min(nToGet - n - 1, chunkSize - 1)
            Dim value As Double = rnd.NextDouble()
            sum += value
            n += 1
'            bin.Write(value)
         Next
      Next
'       bin.Seek(0, SeekOrigin.Begin)
'       bin.Write(n)
'       bin.Close()
      Return New Tuple(Of Double, Long)(sum/n, n)
   End Function
End Module
' The example displays output like the following:
'   Sample mean: 0.500022771458399, N = 200,000,000

Anda berulang kali menggabungkan string besar.

Karena string tidak dapat diubah, setiap operasi perangkaian string membuat string baru. Dampak untuk string kecil, atau untuk sejumlah kecil operasi perangkaian, dapat diabaikan. Tetapi untuk string besar atau sejumlah besar operasi perangkaian, perangkaian string dapat menyebabkan sejumlah besar alokasi memori dan fragmentasi memori, performa yang buruk, dan mungkin OutOfMemoryException pengecualian.

Saat menggabungkan string besar atau melakukan sejumlah besar operasi perangkaian, Anda harus menggunakan StringBuilder kelas alih-alih String kelas . Setelah Anda selesai memanipulasi string, konversikan StringBuilder instans menjadi string dengan memanggil StringBuilder.ToString metode .

Anda menyematkan sejumlah besar objek dalam memori.

Menyematkan sejumlah besar objek dalam memori untuk waktu yang lama dapat menyulitkan pengumpul sampah untuk mengalokasikan blok memori yang berdampingan. Jika Anda telah menyematkan sejumlah besar objek dalam memori, misalnya dengan menggunakan fixed pernyataan di C# atau dengan memanggil GCHandle.Alloc(Object, GCHandleType) metode dengan jenis GCHandleType.Pinnedhandel , Anda dapat melakukan hal berikut untuk mengatasi OutOfMemoryException pengecualian.

  • Mengevaluasi apakah setiap objek benar-benar perlu disematkan,

  • Pastikan bahwa setiap objek tidak disematkan sesegera mungkin.

  • Pastikan bahwa setiap panggilan ke GCHandle.Alloc(Object, GCHandleType) metode untuk menyematkan memori memiliki panggilan yang sesuai dengan metode untuk melepas sematan memori tersebut GCHandle.Free .

Instruksi perantara Microsoft (MSIL) berikut memberikan OutOfMemoryException pengecualian:

Konstruktor

OutOfMemoryException()

Menginisialisasi instans baru kelas OutOfMemoryException.

OutOfMemoryException(SerializationInfo, StreamingContext)
Kedaluwarsa.

Menginisialisasi instans OutOfMemoryException baru kelas dengan data berseri.

OutOfMemoryException(String)

Menginisialisasi instans OutOfMemoryException baru kelas dengan pesan kesalahan tertentu.

OutOfMemoryException(String, Exception)

Menginisialisasi instans OutOfMemoryException baru kelas dengan pesan kesalahan tertentu dan referensi ke pengecualian dalam yang merupakan penyebab pengecualian ini.

Properti

Data

Mendapatkan kumpulan pasangan kunci/nilai yang memberikan informasi tambahan yang ditentukan pengguna tentang pengecualian.

(Diperoleh dari Exception)
HelpLink

Mendapatkan atau mengatur tautan ke file bantuan yang terkait dengan pengecualian ini.

(Diperoleh dari Exception)
HResult

Mendapatkan atau mengatur HRESULT, nilai numerik berkode yang ditetapkan ke pengecualian tertentu.

(Diperoleh dari Exception)
InnerException

Mendapatkan instans Exception yang menyebabkan pengecualian saat ini.

(Diperoleh dari Exception)
Message

Mendapatkan pesan yang menjelaskan pengecualian saat ini.

(Diperoleh dari Exception)
Source

Get dan set nama aplikasi atau objek yang menyebabkan kesalahan.

(Diperoleh dari Exception)
StackTrace

Mendapatkan representasi string dari bingkai langsung pada tumpukan panggilan.

(Diperoleh dari Exception)
TargetSite

Mendapatkan metode yang melemparkan pengecualian saat ini.

(Diperoleh dari Exception)

Metode

Equals(Object)

Menentukan apakah objek yang ditentukan sama dengan objek saat ini.

(Diperoleh dari Object)
GetBaseException()

Ketika ditimpa di kelas turunan Exception , mengembalikan yang merupakan akar penyebab dari satu atau beberapa pengecualian berikutnya.

(Diperoleh dari Exception)
GetHashCode()

Berfungsi sebagai fungsi hash default.

(Diperoleh dari Object)
GetObjectData(SerializationInfo, StreamingContext)
Kedaluwarsa.

Saat ditimpa di kelas turunan SerializationInfo , mengatur dengan informasi tentang pengecualian.

(Diperoleh dari Exception)
GetType()

Mendapatkan jenis runtime dari instans saat ini.

(Diperoleh dari Exception)
MemberwiseClone()

Membuat salinan dangkal dari saat ini Object.

(Diperoleh dari Object)
ToString()

Membuat dan mengembalikan representasi string dari pengecualian saat ini.

(Diperoleh dari Exception)

Acara

SerializeObjectState
Kedaluwarsa.

Terjadi ketika pengecualian diserialisasikan untuk membuat objek status pengecualian yang berisi data berseri tentang pengecualian.

(Diperoleh dari Exception)

Berlaku untuk

Lihat juga