OutOfMemoryException 클래스

정의

프로그램을 계속 실행하기 위한 메모리가 부족할 때 throw되는 예외입니다.

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
상속
OutOfMemoryException
상속
OutOfMemoryException
파생
특성

설명

OutOfMemoryException 는 값이 0x8007000E HRESULT COR_E_OUTOFMEMORY를 사용합니다.

인스턴스의 초기 속성 값의 목록을 OutOfMemoryException, 참조는 OutOfMemoryException 생성자입니다.

참고

상속된 속성의 값은 Data 항상 null입니다.

OutOfMemoryException 예외에는 두 가지 주요 원인이 있습니다.

  • 개체의 속성에 StringBuilder 정의된 길이를 초과하여 개체를 확장하려고 합니다 StringBuilder.MaxCapacity .

  • 공용 언어 런타임은 작업을 성공적으로 수행하기에 충분한 연속 메모리를 할당할 수 없습니다. 이 예외는 메모리 할당이 필요한 속성 할당 또는 메서드 호출에 의해 throw될 수 있습니다. 예외의 OutOfMemoryException 원인에 대한 자세한 내용은 블로그 게시물 "메모리 부족"이 실제 메모리를 참조하지 않음을 참조하세요.

    이 유형의 OutOfMemoryException 예외는 치명적인 오류를 나타냅니다. 예외를 처리하도록 선택하는 경우 다음 예제와 같이 메서드를 catch 호출 Environment.FailFast 하여 앱을 종료하고 시스템 이벤트 로그에 항목을 추가하는 블록을 포함해야 합니다.

    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...
    

예외가 throw되는 조건 중 일부와 예외를 제거하기 위해 수행할 수 있는 작업에는 다음이 포함됩니다.

메서드를 호출하고 StringBuilder.Insert 있습니다.

개체의 StringBuilder 길이를 속성에 지정된 크기 이상으로 늘리려고 합니다 StringBuilder.MaxCapacity . 다음 예제에서는 개체의 OutOfMemoryException 속성이 최대 용량을 초과하는 문자열을 삽입하려고 할 Length 때 메서드를 호출 StringBuilder.Insert(Int32, String, Int32) 하여 throw된 예외를 보여 줍니다.

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.

다음 중 하나를 수행하여 오류를 해결할 수 있습니다.

앱은 32비트 프로세스로 실행됩니다.

32비트 프로세스는 32비트 시스템에 최대 2GB의 가상 사용자 모드 메모리를 할당하고 64비트 시스템에는 4GB의 가상 사용자 모드 메모리를 할당할 수 있습니다. 이렇게 하면 큰 할당이 필요할 때 공용 언어 런타임에서 충분한 연속 메모리를 할당하기가 더 어려워질 수 있습니다. 반면 64비트 프로세스는 최대 8TB의 가상 메모리를 할당할 수 있습니다. 이 예외를 해결하려면 64비트 플랫폼을 대상으로 앱을 다시 컴파일합니다. Visual Studio에서 특정 플랫폼을 대상으로 하는 방법에 대한 자세한 내용은 방법: 대상 플랫폼으로 프로젝트 구성을 참조하세요.

앱이 관리되지 않는 리소스를 유출하고 있습니다.

가비지 수집기는 관리되는 형식에 할당된 메모리를 해제할 수 있지만 운영 체제 핸들(파일, 메모리 매핑된 파일, 파이프, 레지스트리 키 및 대기 핸들에 대한 핸들 포함) 및 Windows API 호출 또는 와 같은 메모리 할당 함수 호출에 의해 직접 할당된 메모리 블록과 같은 malloc관리되지 않는 리소스에 할당된 메모리를 관리하지 않습니다. 관리되지 않는 리소스를 사용하는 형식은 인터페이스를 IDisposable 구현합니다.

관리되지 않는 리소스를 사용하는 형식을 사용하는 경우 사용이 완료되면 해당 메서드를 IDisposable.Dispose 호출해야 합니다. (일부 형식은 함수에서 메서드와 Close 동일한 메서드도 Dispose 구현합니다.) 자세한 내용은 IDisposable을 구현하는 개체 사용 항목을 참조하세요.

관리되지 않는 리소스를 사용하는 형식을 만든 경우 Dispose 패턴을 구현했는지 확인하고 필요한 경우 종료자를 제공했는지 확인합니다. 자세한 내용은 Dispose 메서드 구현Object.Finalize을 참조하세요.

64비트 프로세스에서 큰 배열을 만들려고 합니다.

기본적으로 .NET Framework 공용 언어 런타임은 크기가 2GB를 초과하는 단일 개체를 허용하지 않습니다. 이 기본값을 재정의 <하려면 gcAllowVeryLargeObjects> 구성 파일 설정을 사용하여 총 크기가 2GB를 초과하는 배열을 사용하도록 설정할 수 있습니다. .NET Core에서는 기본적으로 2GB보다 큰 배열에 대한 지원이 사용하도록 설정됩니다.

메모리에서 매우 큰 데이터 집합(예: 배열, 컬렉션 또는 데이터베이스 데이터 세트)으로 작업하고 있습니다.

메모리에 상주하는 데이터 구조 또는 데이터 집합이 너무 커서 공용 언어 런타임에서 해당 메모리에 대해 충분한 연속 메모리를 할당할 수 없는 경우 예외가 발생합니다 OutOfMemoryException .

방지 하기 위해는 OutOfMemoryException 예외 적은 데이터를 메모리에 상주 하거나 데이터 구분 되어 세그먼트로 작은 메모리 할당을 필요로 하는 애플리케이션을 수정 해야 합니다. 예를 들면 다음과 같습니다.

  • 데이터베이스에서 모든 데이터를 검색한 다음 앱에서 필터링하여 서버로의 이동을 최소화하는 경우 앱에 필요한 데이터의 하위 집합만 반환하도록 쿼리를 수정해야 합니다. 큰 테이블로 작업할 때 여러 쿼리는 단일 테이블의 모든 데이터를 검색한 다음 조작하는 것보다 거의 항상 더 효율적입니다.

  • 사용자가 동적으로 만드는 쿼리를 실행하는 경우 쿼리에서 반환되는 레코드 수가 제한되어 있는지 확인해야 합니다.

  • 대형 배열을 사용 하는 경우 또는 다른 컬렉션의 크기가 결과 개체는 OutOfMemoryException 예외를 한 번에 모두 사용 하기 보다는 데이터 하위 집합에서 작동 하도록 애플리케이션을 수정 해야 합니다.

다음 예제에서는 2억 부동 소수점 값으로 구성된 배열을 가져오고 해당 평균을 계산합니다. 예제의 출력은 예제가 평균을 계산하기 전에 전체 배열을 메모리에 저장하기 때문에 가 throw됨을 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.

다음 예제에서는 메모리에 전체 데이터 집합을 저장하지 않고 들어오는 데이터를 처리하고, 필요한 경우 데이터를 파일로 직렬화하여 추가 처리를 허용하고(이 경우 크기가 1GB보다 큰 파일을 생성하기 때문에 이러한 줄은 예제에서 주석 처리됨) 계산된 평균과 사례 수를 호출 루틴에 반환하여 예외를 제거 OutOfMemoryException 합니다.

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

큰 문자열을 반복적으로 연결합니다.

문자열은 변경할 수 있으므로 각 문자열 연결 작업은 새 문자열을 만듭니다. 작은 문자열 또는 적은 수의 연결 작업에 미치는 영향은 무시할 수 있습니다. 그러나 큰 문자열 또는 매우 많은 수의 연결 작업의 경우 문자열 연결은 많은 수의 메모리 할당 및 메모리 조각화, 성능 저하 및 OutOfMemoryException 예외로 이어질 수 있습니다.

큰 문자열을 연결하거나 많은 수의 연결 작업을 수행하는 경우 클래스 대신 클래스를 StringBuilderString 사용해야 합니다. 문자열 조작을 마쳤으면 메서드를 호출 StringBuilder.ToString 하여 instance 문자열로 변환 StringBuilder 합니다.

많은 수의 개체를 메모리에 고정합니다.

많은 수의 개체를 오랫동안 메모리에 고정하면 가비지 수집기에서 연속 메모리 블록을 할당하기가 어려울 수 있습니다. 예를 들어 C#의 문을 사용 fixed 하거나 핸들 형식으로 메서드를 호출 GCHandle.Alloc(Object, GCHandleType) 하여 메모리에 많은 수의 GCHandleType.Pinned개체를 고정한 경우 다음을 수행하여 예외를 OutOfMemoryException 해결할 수 있습니다.

  • 각 개체를 실제로 고정해야 하는지 여부를 평가합니다.

  • 각 개체가 가능한 한 빨리 고정 해제되었는지 확인합니다.

  • 메모리를 고정하는 메서드에 대한 GCHandle.Alloc(Object, GCHandleType) 각 호출에 해당 메모리를 고정 해제하는 GCHandle.Free 메서드에 대한 해당 호출이 있는지 확인합니다.

다음 MSIL(Microsoft Intermediate) 지침은 예외를 throw OutOfMemoryException 합니다.

생성자

OutOfMemoryException()

OutOfMemoryException 클래스의 새 인스턴스를 초기화합니다.

OutOfMemoryException(SerializationInfo, StreamingContext)
사용되지 않음.

serialize된 데이터를 사용하여 OutOfMemoryException 클래스의 새 인스턴스를 초기화합니다.

OutOfMemoryException(String)

지정된 오류 메시지를 사용하여 OutOfMemoryException 클래스의 새 인스턴스를 초기화합니다.

OutOfMemoryException(String, Exception)

지정된 오류 메시지와 해당 예외의 원인인 내부 예외에 대한 참조를 사용하여 OutOfMemoryException 클래스의 새 인스턴스를 초기화합니다.

속성

Data

예외에 대한 사용자 정의 정보를 추가로 제공하는 키/값 쌍 컬렉션을 가져옵니다.

(다음에서 상속됨 Exception)
HelpLink

이 예외와 연결된 도움말 파일에 대한 링크를 가져오거나 설정합니다.

(다음에서 상속됨 Exception)
HResult

특정 예외에 할당된 코드화된 숫자 값인 HRESULT를 가져오거나 설정합니다.

(다음에서 상속됨 Exception)
InnerException

현재 예외를 발생시킨 Exception 인스턴스를 가져옵니다.

(다음에서 상속됨 Exception)
Message

현재 예외를 설명하는 메시지를 가져옵니다.

(다음에서 상속됨 Exception)
Source

오류를 발생시키는 애플리케이션 또는 개체의 이름을 가져오거나 설정합니다.

(다음에서 상속됨 Exception)
StackTrace

호출 스택의 직접 실행 프레임 문자열 표현을 가져옵니다.

(다음에서 상속됨 Exception)
TargetSite

현재 예외를 throw하는 메서드를 가져옵니다.

(다음에서 상속됨 Exception)

메서드

Equals(Object)

지정된 개체가 현재 개체와 같은지 확인합니다.

(다음에서 상속됨 Object)
GetBaseException()

파생 클래스에서 재정의된 경우 하나 이상의 후속 예외의 근본 원인이 되는 Exception 을 반환합니다.

(다음에서 상속됨 Exception)
GetHashCode()

기본 해시 함수로 작동합니다.

(다음에서 상속됨 Object)
GetObjectData(SerializationInfo, StreamingContext)
사용되지 않음.

파생 클래스에서 재정의된 경우 예외에 관한 정보를 SerializationInfo 에 설정합니다.

(다음에서 상속됨 Exception)
GetType()

현재 인스턴스의 런타임 형식을 가져옵니다.

(다음에서 상속됨 Exception)
MemberwiseClone()

현재 Object의 단순 복사본을 만듭니다.

(다음에서 상속됨 Object)
ToString()

현재 예외에 대한 문자열 표현을 만들고 반환합니다.

(다음에서 상속됨 Exception)

이벤트

SerializeObjectState
사용되지 않음.

예외에 대한 serialize된 데이터가 들어 있는 예외 상태 개체가 만들어지도록 예외가 serialize될 때 발생합니다.

(다음에서 상속됨 Exception)

적용 대상

추가 정보