次の方法で共有


OutOfMemoryException クラス

定義

プログラムの実行を続行するのに十分なメモリがない場合にスローされる例外。

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 例外には、主に次の 2 つの原因があります。

  • StringBuilder.MaxCapacity プロパティで定義されている長さを超えて、StringBuilder オブジェクトを拡張しようとしています。

  • 共通言語ランタイムは、操作を正常に実行するのに十分な連続したメモリを割り当てることができません。 この例外は、メモリ割り当てを必要とするプロパティの割り当てまたはメソッド呼び出しによってスローされます。 例外の原因の詳細については、「メモリ不足」が物理メモリを参照しない ブログ記事を参照してください。

    この種類の OutOfMemoryException 例外は、致命的なエラーを表します。 例外を処理する場合は、次の例のように、Environment.FailFast メソッドを呼び出してアプリを終了し、システム イベント ログにエントリを追加する catch ブロックを含める必要があります。

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

例外がスローされる条件と、例外を排除するために実行できるアクションには、次のようなものがあります。

StringBuilder.Insert メソッドを呼び出しています。

StringBuilder オブジェクトの長さを、StringBuilder.MaxCapacity プロパティで指定されたサイズを超えて長くしようとしています。 次の例は、オブジェクトの Length プロパティが最大容量を超える文字列を挿入しようとしたときに、StringBuilder.Insert(Int32, String, Int32) メソッドの呼び出しによってスローされる OutOfMemoryException 例外を示しています。

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 ビット システムでは最大 2 GB の仮想ユーザー モード メモリを割り当て、64 ビット システムでは 4 GB の仮想ユーザー モード メモリを割り当てることができます。 これにより、大きな割り当てが必要な場合に、共通言語ランタイムで十分な連続したメモリを割り当てることが困難になる可能性があります。 これに対し、64 ビット プロセスでは、最大 8 TB の仮想メモリを割り当てることができます。 この例外に対処するには、アプリを再コンパイルして 64 ビット プラットフォームをターゲットにします。 Visual Studio で特定のプラットフォームをターゲットにする方法については、「方法: ターゲット プラットフォームにプロジェクトを構成する」を参照してください。

アプリがアンマネージド リソースをリーク

ガベージ コレクターは、マネージド型に割り当てられたメモリを解放できますが、オペレーティング システム ハンドル (ファイルへのハンドル、メモリ マップド ファイル、パイプ、レジストリ キー、待機ハンドルなど) や、Windows API 呼び出しまたは mallocなどのメモリ割り当て関数の呼び出しによって直接割り当てられたメモリ ブロックなどのアンマネージ リソースに割り当てられたメモリは管理されません。 アンマネージ リソースを使用する型は、IDisposable インターフェイスを実装します。

アンマネージド リソースを使用する型を使用する場合は、その IDisposable.Dispose メソッドの使用が完了したら、そのメソッドを必ず呼び出す必要があります。 (一部の型では、Dispose メソッドと関数内で同一の Close メソッドも実装されます)。詳細については、「IDisposable を実装するオブジェクトの使用 トピックを参照してください。

アンマネージ リソースを使用する型を作成した場合は、Dispose パターンを実装し、必要に応じてファイナライザーを提供していることを確認します。 詳細については、「Dispose メソッドの実装Object.Finalize」を参照してください。

64 ビット プロセス で大きな配列を作成しようとしています

既定では、.NET Framework の共通言語ランタイムでは、サイズが 2 GB を超える 1 つのオブジェクトは許可されません。 この既定値をオーバーライドするには、<gcAllowVeryLargeObjects> 構成ファイル設定を使用して、合計サイズが 2 GB を超える配列を有効にすることができます。 .NET Core では、2 GB を超える配列のサポートが既定で有効になっています。

メモリ内の非常に大きなデータ セット (配列、コレクション、データベース データ セットなど) を操作しています。

メモリ内に存在するデータ構造またはデータ セットが非常に大きくなり、共通言語ランタイムが十分な連続したメモリを割り当てることができない場合、OutOfMemoryException 例外が発生します。

OutOfMemoryException 例外を防ぐには、メモリに格納されるデータが少ないようにアプリケーションを変更するか、データをより小さなメモリ割り当てを必要とするセグメントに分割する必要があります。 例えば:

  • データベースからすべてのデータを取得し、アプリでフィルター処理してサーバーへの移動を最小限に抑える場合は、アプリに必要なデータのサブセットのみを返すようにクエリを変更する必要があります。 大きなテーブルを操作する場合、1 つのテーブル内のすべてのデータを取得して操作するよりも、ほとんどの場合、複数のクエリの方が効率的です。

  • ユーザーが動的に作成するクエリを実行する場合は、クエリによって返されるレコードの数が制限されていることを確認する必要があります。

  • サイズが OutOfMemoryException 例外になる大きな配列またはその他のコレクション オブジェクトを使用している場合は、一度にすべて操作するのではなく、サブセット内のデータを処理するようにアプリケーションを変更する必要があります。

次の例では、2 億個の浮動小数点値で構成される配列を取得し、その平均値を計算します。 この例の出力は、平均を計算する前に配列全体をメモリに格納するため、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.

次の例では、データ セット全体をメモリに格納せずに受信データを処理し、さらに処理を許可するために必要に応じてデータをファイルにシリアル化し (この例では、サイズが 1 GB を超えるファイルを生成するため、これらの行はコメント アウトされます)、計算された平均とケース数を呼び出し元ルーチンに返すことで、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 例外が発生する可能性があります。

大きな文字列を連結する場合、または多数の連結操作を実行する場合は、String クラスの代わりに StringBuilder クラスを使用する必要があります。 文字列の操作が完了したら、StringBuilder.ToString メソッドを呼び出して、StringBuilder インスタンスを文字列に変換します。

メモリ内に多数のオブジェクトをピン留めします。

メモリに多数のオブジェクトを長時間ピン留めすると、ガベージ コレクターが連続するメモリ ブロックを割り当てることが困難になる場合があります。 メモリ内に多数のオブジェクトを固定している場合 (たとえば、C# で fixed ステートメントを使用するか、ハンドルの種類が GCHandleType.PinnedGCHandle.Alloc(Object, GCHandleType) メソッドを呼び出すことによって)、次の操作を実行して OutOfMemoryException 例外に対処できます。

  • 各オブジェクトを本当にピン留めする必要があるかどうかを評価します。

  • 各オブジェクトができるだけ早くピン留めされていないことを確認します。

  • メモリをピン留めする GCHandle.Alloc(Object, GCHandleType) メソッドの各呼び出しに、そのメモリを固定解除するための GCHandle.Free メソッドへの対応する呼び出しがあることを確認します。

次の Microsoft Intermediate (MSIL) 命令では、OutOfMemoryException 例外がスローされます。

コンストラクター

OutOfMemoryException()

OutOfMemoryException クラスの新しいインスタンスを初期化します。

OutOfMemoryException(SerializationInfo, StreamingContext)
古い.

シリアル化されたデータを使用して、OutOfMemoryException クラスの新しいインスタンスを初期化します。

OutOfMemoryException(String, Exception)

指定したエラー メッセージと、この例外の原因である内部例外への参照を使用して、OutOfMemoryException クラスの新しいインスタンスを初期化します。

OutOfMemoryException(String)

指定したエラー メッセージを使用して、OutOfMemoryException クラスの新しいインスタンスを初期化します。

プロパティ

Data

例外に関する追加のユーザー定義情報を提供するキーと値のペアのコレクションを取得します。

(継承元 Exception)
HelpLink

この例外に関連付けられているヘルプ ファイルへのリンクを取得または設定します。

(継承元 Exception)
HResult

特定の例外に割り当てられるコード化された数値である HRESULT を取得または設定します。

(継承元 Exception)
InnerException

現在の例外の原因となった Exception インスタンスを取得します。

(継承元 Exception)
Message

現在の例外を説明するメッセージを取得します。

(継承元 Exception)
Source

エラーの原因となるアプリケーションまたはオブジェクトの名前を取得または設定します。

(継承元 Exception)
StackTrace

呼び出し履歴のイミディエイト フレームの文字列表現を取得します。

(継承元 Exception)
TargetSite

現在の例外をスローするメソッドを取得します。

(継承元 Exception)

メソッド

Equals(Object)

指定したオブジェクトが現在のオブジェクトと等しいかどうかを判断します。

(継承元 Object)
GetBaseException()

派生クラスでオーバーライドされた場合、1 つ以上の後続の例外の根本原因である Exception を返します。

(継承元 Exception)
GetHashCode()

既定のハッシュ関数として機能します。

(継承元 Object)
GetObjectData(SerializationInfo, StreamingContext)
古い.

派生クラスでオーバーライドされた場合は、例外に関する情報を使用して SerializationInfo を設定します。

(継承元 Exception)
GetType()

現在のインスタンスのランタイム型を取得します。

(継承元 Exception)
MemberwiseClone()

現在の Objectの簡易コピーを作成します。

(継承元 Object)
ToString()

現在の例外の文字列形式を作成して返します。

(継承元 Exception)

イベント

SerializeObjectState
古い.

例外に関するシリアル化されたデータを含む例外状態オブジェクトを作成するために例外がシリアル化されるときに発生します。

(継承元 Exception)

適用対象

こちらもご覧ください