OutOfMemoryException Klasa
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Wyjątek zgłaszany, gdy za mało pamięci, aby kontynuować wykonywanie programu.
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
- Dziedziczenie
- Dziedziczenie
- Pochodne
- Atrybuty
Uwagi
OutOfMemoryException używa COR_E_OUTOFMEMORY
HRESULT, która ma wartość 0x8007000E.
Aby uzyskać listę początkowych wartości właściwości dla wystąpienia OutOfMemoryException, zobacz konstruktory OutOfMemoryException.
Nuta
Wartość dziedziczonej właściwości Data jest zawsze null
.
Wyjątek OutOfMemoryException ma dwie główne przyczyny:
Próbujesz rozwinąć obiekt StringBuilder poza długością zdefiniowaną przez jego właściwość StringBuilder.MaxCapacity.
Środowisko uruchomieniowe języka wspólnego nie może przydzielić wystarczającej ilości pamięci, aby pomyślnie wykonać operację. Ten wyjątek może zostać zgłoszony przez dowolne przypisanie właściwości lub wywołanie metody, które wymaga alokacji pamięci. Aby uzyskać więcej informacji na temat przyczyny wyjątku OutOfMemoryException, zobacz wpis w blogu "Brak pamięci" Nie odnosi się do pamięci fizycznej.
Ten typ wyjątku OutOfMemoryException reprezentuje katastrofalną awarię. Jeśli zdecydujesz się obsłużyć wyjątek, należy uwzględnić blok
catch
, który wywołuje metodę Environment.FailFast, aby zakończyć działanie aplikacji i dodać wpis do dziennika zdarzeń systemu, jak w poniższym przykładzie.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...
Niektóre warunki, w których zgłaszany jest wyjątek, a akcje, które można podjąć, aby go wyeliminować, obejmują następujące elementy:
Wywołujesz metodę StringBuilder.Insert.
Próbujesz zwiększyć długość obiektu StringBuilder poza rozmiar określony przez jego właściwość StringBuilder.MaxCapacity. Poniższy przykład ilustruje wyjątek OutOfMemoryException zgłoszony przez wywołanie metody StringBuilder.Insert(Int32, String, Int32), gdy przykład próbuje wstawić ciąg, który spowoduje, że właściwość Length obiektu przekroczy maksymalną pojemność.
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.
Aby rozwiązać ten problem, możesz wykonać jedną z następujących czynności:
Zastąp wywołanie konstruktora StringBuilder.StringBuilder(Int32, Int32) wywołaniem dowolnego innego przeciążenia konstruktora StringBuilder. Maksymalna pojemność obiektu StringBuilder zostanie ustawiona na wartość domyślną, czyli Int32.MaxValue.
Wywołaj konstruktor StringBuilder.StringBuilder(Int32, Int32) z wartością
maxCapacity
, która jest wystarczająco duża, aby pomieścić wszelkie rozszerzenia obiektu StringBuilder.
Aplikacja jest uruchamiana jako proces 32-bitowy.
Procesy 32-bitowe mogą przydzielić maksymalnie 2 GB pamięci w trybie użytkownika wirtualnego w systemach 32-bitowych i 4 GB pamięci w trybie użytkownika wirtualnego w systemach 64-bitowych. Może to utrudnić środowisko uruchomieniowe języka wspólnego przydzielenie wystarczającej ilości ciągłej pamięci, gdy potrzebna jest duża alokacja. Natomiast 64-bitowe procesy mogą przydzielić do 8 TB pamięci wirtualnej. Aby rozwiązać ten wyjątek, ponownie skompiluj aplikację w celu kierowania platformy 64-bitowej. Aby uzyskać informacje na temat określania docelowych platform w programie Visual Studio, zobacz Instrukcje: konfigurowanie projektów na platformach docelowych.
Aplikacja przecieka niezarządzanych zasobów
Mimo że moduł odśmiecywania pamięci jest w stanie zwolnić pamięć przydzieloną do typów zarządzanych, nie zarządza pamięcią przydzieloną do niezarządzanych zasobów, takich jak dojścia systemu operacyjnego (w tym dojścia do plików, plików mapowanych pamięci, potoków, kluczy rejestru i uchwytów oczekiwania) oraz bloków pamięci przydzielonych bezpośrednio przez wywołania interfejsu API systemu Windows lub wywołań funkcji alokacji pamięci, takich jak malloc
. Typy wykorzystujące niezarządzane zasoby implementują interfejs IDisposable.
Jeśli używasz typu korzystającego z zasobów niezarządzanych, po zakończeniu korzystania z niej należy wywołać metodę IDisposable.Dispose. (Niektóre typy implementują również metodę
Jeśli utworzono typ używający zasobów niezarządzanych, upewnij się, że zaimplementowano wzorzec Dispose i, w razie potrzeby, podano finalizator. Aby uzyskać więcej informacji, zobacz Implementowanie metody Dispose i Object.Finalize.
Próbujesz utworzyć dużą tablicę w procesie 64-bitowym
Domyślnie środowisko uruchomieniowe języka wspólnego w programie .NET Framework nie zezwala na pojedyncze obiekty, których rozmiar przekracza 2 GB. Aby zastąpić tę wartość domyślną, możesz użyć ustawienia <gcAllowVeryLargeObjects> pliku konfiguracji, aby włączyć tablice, których całkowity rozmiar przekracza 2 GB. Na platformie .NET Core obsługa tablic większych niż 2 GB jest domyślnie włączona.
Pracujesz z bardzo dużymi zestawami danych (takimi jak tablice, kolekcje lub zestawy danych bazy danych) w pamięci.
Gdy struktury danych lub zestawy danych, które znajdują się w pamięci, stają się tak duże, że środowisko uruchomieniowe języka wspólnego nie może przydzielić wystarczającej ilości pamięci dla nich, wynik wyjątku OutOfMemoryException.
Aby zapobiec wyjątkom OutOfMemoryException, należy zmodyfikować aplikację tak, aby mniej danych mieściło się w pamięci lub dane zostały podzielone na segmenty wymagające mniejszych alokacji pamięci. Na przykład:
Jeśli pobierasz wszystkie dane z bazy danych, a następnie filtrujesz je w aplikacji, aby zminimalizować podróże do serwera, należy zmodyfikować zapytania tak, aby zwracały tylko podzestaw danych potrzebnych aplikacji. Podczas pracy z dużymi tabelami wiele zapytań jest prawie zawsze bardziej wydajnych niż pobieranie wszystkich danych w jednej tabeli, a następnie manipulowanie nimi.
Jeśli wykonujesz zapytania tworzone dynamicznie przez użytkowników, upewnij się, że liczba rekordów zwracanych przez zapytanie jest ograniczona.
Jeśli używasz dużych tablic lub innych obiektów kolekcji, których rozmiar powoduje wyjątek OutOfMemoryException, należy zmodyfikować aplikację, aby pracować z danymi w podzestawach, a nie pracować z nim jednocześnie.
Poniższy przykład pobiera tablicę składającą się z 200 milionów wartości zmiennoprzecinkowych, a następnie oblicza ich średnią. Dane wyjściowe z przykładu pokazują, że ponieważ przykład przechowuje całą tablicę w pamięci, zanim obliczy średnią, zostanie zgłoszony 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.
Poniższy przykład eliminuje wyjątek OutOfMemoryException przez przetwarzanie danych przychodzących bez przechowywania całego zestawu danych w pamięci, serializowanie danych do pliku w razie potrzeby w celu zezwolenia na dalsze przetwarzanie (te wiersze są komentowane w tym przykładzie, ponieważ w tym przypadku tworzą plik, którego rozmiar jest większy niż 1 GB) i zwraca średnią obliczeniową i liczbę przypadków do procedury wywoływania.
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
Wielokrotnie łączysz duże ciągi.
Ponieważ ciągi są niezmienne, każda operacja łączenia ciągów tworzy nowy ciąg. Wpływ na małe ciągi lub niewielką liczbę operacji łączenia jest niewielki. Jednak w przypadku dużych ciągów lub bardzo dużej liczby operacji łączenia łączenie ciągów może prowadzić do dużej liczby alokacji pamięci i fragmentacji pamięci, niskiej wydajności i prawdopodobnie OutOfMemoryException wyjątków.
Podczas łączenia dużych ciągów lub wykonywania dużej liczby operacji łączenia należy użyć klasy StringBuilder zamiast klasy String. Po zakończeniu manipulowania ciągiem przekonwertuj wystąpienie StringBuilder na ciąg, wywołując metodę StringBuilder.ToString.
Przypinasz dużą liczbę obiektów w pamięci.
Przypinanie dużej liczby obiektów w pamięci przez długi czas może utrudnić modułowi odśmiecania pamięci przydzielanie ciągłych bloków pamięci. Jeśli przypięliśmy dużą liczbę obiektów w pamięci, na przykład przy użyciu instrukcji fixed
w języku C# lub wywołując metodę GCHandle.Alloc(Object, GCHandleType) z typem uchwytu GCHandleType.Pinned, możesz wykonać następujące czynności, aby rozwiązać problem OutOfMemoryException wyjątku.
Oceń, czy każdy obiekt musi być przypięty,
Upewnij się, że każdy obiekt jest odpiętywany tak szybko, jak to możliwe.
Upewnij się, że każde wywołanie metody GCHandle.Alloc(Object, GCHandleType) w celu przypięcia pamięci ma odpowiednie wywołanie metody GCHandle.Free, aby odpiąć tę pamięć.
Następujące instrukcje dotyczące platformy Microsoft Intermediate (MSIL) zgłaszają wyjątek OutOfMemoryException:
Konstruktory
OutOfMemoryException() |
Inicjuje nowe wystąpienie klasy OutOfMemoryException. |
OutOfMemoryException(SerializationInfo, StreamingContext) |
Przestarzałe.
Inicjuje nowe wystąpienie klasy OutOfMemoryException z serializowanymi danymi. |
OutOfMemoryException(String, Exception) |
Inicjuje nowe wystąpienie klasy OutOfMemoryException z określonym komunikatem o błędzie i odwołaniem do wyjątku wewnętrznego, który jest przyczyną tego wyjątku. |
OutOfMemoryException(String) |
Inicjuje nowe wystąpienie klasy OutOfMemoryException z określonym komunikatem o błędzie. |
Właściwości
Data |
Pobiera kolekcję par klucz/wartość, które zapewniają dodatkowe informacje zdefiniowane przez użytkownika dotyczące wyjątku. (Odziedziczone po Exception) |
HelpLink |
Pobiera lub ustawia link do pliku pomocy skojarzonego z tym wyjątkiem. (Odziedziczone po Exception) |
HResult |
Pobiera lub ustawia HRESULT, zakodowaną wartość liczbową przypisaną do określonego wyjątku. (Odziedziczone po Exception) |
InnerException |
Pobiera wystąpienie Exception, które spowodowało bieżący wyjątek. (Odziedziczone po Exception) |
Message |
Pobiera komunikat opisujący bieżący wyjątek. (Odziedziczone po Exception) |
Source |
Pobiera lub ustawia nazwę aplikacji lub obiektu, który powoduje błąd. (Odziedziczone po Exception) |
StackTrace |
Pobiera reprezentację ciągu natychmiastowych ramek na stosie wywołań. (Odziedziczone po Exception) |
TargetSite |
Pobiera metodę, która zgłasza bieżący wyjątek. (Odziedziczone po Exception) |
Metody
Equals(Object) |
Określa, czy określony obiekt jest równy bieżącemu obiektowi. (Odziedziczone po Object) |
GetBaseException() |
Po zastąpieniu w klasie pochodnej zwraca Exception, która jest główną przyczyną co najmniej jednego kolejnego wyjątku. (Odziedziczone po Exception) |
GetHashCode() |
Służy jako domyślna funkcja skrótu. (Odziedziczone po Object) |
GetObjectData(SerializationInfo, StreamingContext) |
Przestarzałe.
Po zastąpieniu w klasie pochodnej ustawia SerializationInfo z informacjami o wyjątku. (Odziedziczone po Exception) |
GetType() |
Pobiera typ środowiska uruchomieniowego bieżącego wystąpienia. (Odziedziczone po Exception) |
MemberwiseClone() |
Tworzy płytkią kopię bieżącego Object. (Odziedziczone po Object) |
ToString() |
Tworzy i zwraca reprezentację ciągu bieżącego wyjątku. (Odziedziczone po Exception) |
Zdarzenia
SerializeObjectState |
Przestarzałe.
Występuje, gdy wyjątek jest serializowany w celu utworzenia obiektu stanu wyjątku zawierającego serializowane dane dotyczące wyjątku. (Odziedziczone po Exception) |