OutOfMemoryException Třída
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Výjimka, která se vyvolá, když není dostatek paměti pro pokračování v provádění 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
- Dědičnost
- Dědičnost
- Odvozené
- Atributy
Poznámky
OutOfMemoryException používá HODNOTU HRESULT COR_E_OUTOFMEMORY, která má hodnotu 0x8007000E.
Seznam počátečních hodnot vlastností pro instanci OutOfMemoryExceptionnaleznete v konstruktoru OutOfMemoryException.
Poznámka:
Hodnota zděděné Data vlastnosti je vždy null.
Výjimka OutOfMemoryException má dvě hlavní příčiny:
Pokoušíte se rozšířit StringBuilder objekt nad rámec délky definované jeho StringBuilder.MaxCapacity vlastností.
Modul CLR (Common Language Runtime) nemůže přidělit dostatek souvislé paměti pro úspěšné provedení operace. Tuto výjimku může vyvolat jakékoli přiřazení vlastnosti nebo volání metody, které vyžaduje přidělení paměti. Další informace o příčině OutOfMemoryException výjimky naleznete v blogovém příspěvku "Nedostatek paměti" neodkazuje na fyzickou paměť.
Tento typ OutOfMemoryException výjimky představuje závažné selhání. Pokud se rozhodnete výjimku zpracovat, měli byste zahrnout
catchblok, který volá metodu Environment.FailFast pro ukončení aplikace a přidat položku do systémového protokolu událostí, jak je znázorněno v následujícím příkladu.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...
Mezi podmínky, za kterých je výjimka vyvoláná, a akce, které můžete provést k odstranění, zahrnují následující:
Voláte metodu StringBuilder.Insert .
Pokoušíte se zvětšit délku objektu StringBuilder nad velikost určenou jeho StringBuilder.MaxCapacity vlastností. Následující příklad znázorňuje OutOfMemoryException výjimku vyvolanou voláním StringBuilder.Insert(Int32, String, Int32) metody, když se příklad pokusí vložit řetězec, který by způsobil, že vlastnost objektu Length překročila jeho maximální kapacitu.
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.
Pokud chcete chybu vyřešit, můžete provést některou z následujících akcí:
Nahraďte volání StringBuilder.StringBuilder(Int32, Int32) konstruktoru voláním jakéhokoli jiného StringBuilder přetížení konstruktoru. Maximální kapacita objektu StringBuilder bude nastavena na výchozí hodnotu, což je Int32.MaxValue.
StringBuilder.StringBuilder(Int32, Int32) Zavolejte konstruktor s
maxCapacityhodnotou, která je dostatečně velká, aby vyhovovala všem rozšířením objektuStringBuilder.
Aplikace běží jako 32bitový proces.
32bitové procesy mohou přidělit maximálně 2 GB paměti virtuálního uživatelského režimu v 32bitových systémech a 4 GB paměti virtuálního uživatelského režimu v 64bitových systémech. To může ztížit přidělení dostatečné souvislé paměti v případě potřeby velkého přidělení modulu CLR (Common Language Runtime). Naproti tomu 64bitové procesy můžou přidělit až 8 TB virtuální paměti. Pokud chcete tuto výjimku vyřešit, překompilujte aplikaci tak, aby cílila na 64bitovou platformu. Informace o cílení na konkrétní platformy v sadě Visual Studio najdete v tématu Postupy: Konfigurace projektů na cílové platformy.
Vaše aplikace nespravované prostředky nespravuje
Přestože systém uvolňování paměti dokáže uvolnit paměť přidělenou spravovaným typům, nespravuje paměť přidělenou nespravovaným prostředkům, jako jsou popisovače operačního systému (včetně popisovačů souborů, souborů mapovaných do paměti, kanálů, klíčů registru a popisovačů čekání) a bloků paměti přidělených přímo voláním rozhraní API systému Windows nebo voláním funkcí přidělení paměti, jako mallocjsou . Typy, které využívají nespravované prostředky, implementují IDisposable rozhraní.
Pokud používáte typ, který používá nespravované prostředky, měli byste při jeho použití volat jeho IDisposable.Dispose metodu. (Některé typy také implementují metodu Close , která je stejná ve funkci jako Dispose metoda.) Další informace naleznete v tématu Použití objektů, které implementují IDisposable téma.
Pokud jste vytvořili typ, který používá nespravované prostředky, ujistěte se, že jste implementovali vzor Dispose a v případě potřeby zadali finalizátor. Další informace naleznete v tématu Implementace metody Dispose a Object.Finalize.
Pokoušíte se vytvořit velké pole v 64bitovém procesu.
Modul CLR (Common Language Runtime) v rozhraní .NET Framework ve výchozím nastavení neumožňuje jednotlivé objekty, jejichž velikost přesahuje 2 GB. Pokud chcete toto výchozí nastavení přepsat, můžete použít nastavení konfiguračního <souboru gcAllowVeryLargeObjects> a povolit pole, jejichž celková velikost přesahuje 2 GB. V .NET Core je ve výchozím nastavení povolená podpora polí větších než 2 GB.
Pracujete s velmi velkými sadami dat (jako jsou pole, kolekce nebo databázové datové sady) v paměti.
Když se datové struktury nebo datové sady umístěné v paměti stanou tak velkými, že modul CLR (Common Language Runtime) nemůže přidělit pro ně dostatečnou souvislou paměť, dojde k výjimce OutOfMemoryException .
Chcete-li zabránit OutOfMemoryException výjimkám, je nutné upravit aplikaci tak, aby méně dat bylo v paměti, nebo jsou data rozdělena do segmentů, které vyžadují menší přidělení paměti. Například:
Pokud načítáte všechna data z databáze a pak je filtrujete v aplikaci, abyste minimalizovali cesty na server, měli byste upravit dotazy tak, aby vracely jenom podmnožinu dat, která vaše aplikace potřebuje. Při práci s velkými tabulkami je více dotazů téměř vždy efektivnější než načítání všech dat v jedné tabulce a následné manipulaci s nimi.
Pokud provádíte dotazy, které uživatelé vytvářejí dynamicky, měli byste zajistit, aby byl počet záznamů vrácených dotazem omezený.
Pokud používáte velká pole nebo jiné objekty kolekce, jejichž velikost vede k výjimce OutOfMemoryException , měli byste aplikaci upravit tak, aby fungovala data v podmnožinách, a ne pracovat s ní najednou.
Následující příklad získá matici, která se skládá z 200 milionů hodnot s plovoucí desetinnou čárkou a pak vypočítá jejich střední hodnotu. Výstup z příkladu ukazuje, že protože příklad ukládá celé pole do paměti před tím, než vypočítá střední hodnotu, OutOfMemoryException je vyvolána.
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.
Následující příklad eliminuje OutOfMemoryException výjimku zpracováním příchozích dat bez uložení celé sady dat do paměti, serializace dat do souboru v případě potřeby k povolení dalšího zpracování (tyto řádky jsou v příkladu okomentovány, protože v tomto případě vytvoří soubor, jehož velikost je větší než 1 GB) a vrátí počítanou střední hodnotu a počet případů do volající rutiny.
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
Opakovaně zřetězení velkých řetězců.
Vzhledem k tomu, že řetězce jsou neměnné, každá operace zřetězení řetězců vytvoří nový řetězec. Dopad na malé řetězce nebo malý počet operací zřetězení je zanedbatelný. U velkých řetězců nebo velmi velkého počtu operací zřetězení však může zřetězení řetězců vést k velkému počtu přidělení paměti a fragmentace paměti, nízkému výkonu a pravděpodobně OutOfMemoryException i výjimkám.
Při zřetězení velkých řetězců nebo provádění velkého počtu operací zřetězení byste měli místo třídy použít StringBuilder třídu String . Po dokončení manipulace s řetězcem převeďte StringBuilder instanci na řetězec voláním StringBuilder.ToString metody.
Připnete velký počet objektů v paměti.
Připnutí velkého počtu objektů v paměti po dlouhou dobu může znesnadnit uvolňování paměti přidělení souvislých bloků paměti. Pokud jste připnuli velký počet objektů v paměti, například pomocí fixed příkazu v jazyce C# nebo voláním GCHandle.Alloc(Object, GCHandleType) metody s typem GCHandleType.Pinnedpopisovače , můžete tuto výjimku vyřešit OutOfMemoryException následujícím způsobem.
Vyhodnoťte, jestli je potřeba připnout každý objekt.
Zajistěte, aby se každý objekt co nejdříve odepnul.
Ujistěte se, že každé volání GCHandle.Alloc(Object, GCHandleType) metody připnutí paměti má odpovídající volání GCHandle.Free metody pro odepnutí této paměti.
Následující pokyny microsoft intermediate (MSIL) vyvolá OutOfMemoryException výjimku:
Konstruktory
| Name | Description |
|---|---|
| OutOfMemoryException() |
Inicializuje novou instanci OutOfMemoryException třídy. |
| OutOfMemoryException(SerializationInfo, StreamingContext) |
Zastaralé.
Inicializuje novou instanci OutOfMemoryException třídy serializovanými daty. |
| OutOfMemoryException(String, Exception) |
Inicializuje novou instanci OutOfMemoryException třídy se zadanou chybovou zprávou a odkazem na vnitřní výjimku, která je příčinou této výjimky. |
| OutOfMemoryException(String) |
Inicializuje novou instanci OutOfMemoryException třídy se zadanou chybovou zprávou. |
Vlastnosti
| Name | Description |
|---|---|
| Data |
Získá kolekci párů klíč/hodnota, které poskytují další uživatelem definované informace o výjimce. (Zděděno od Exception) |
| HelpLink |
Získá nebo nastaví odkaz na soubor nápovědy přidružený k této výjimce. (Zděděno od Exception) |
| HResult |
Získá nebo nastaví HRESULT, kódovanou číselnou hodnotu, která je přiřazena ke konkrétní výjimce. (Zděděno od Exception) |
| InnerException |
Exception Získá instanci, která způsobila aktuální výjimku. (Zděděno od Exception) |
| Message |
Získá zprávu, která popisuje aktuální výjimku. (Zděděno od Exception) |
| Source |
Získá nebo nastaví název aplikace nebo objektu, který způsobuje chybu. (Zděděno od Exception) |
| StackTrace |
Získá řetězcové znázornění okamžitých rámců v zásobníku volání. (Zděděno od Exception) |
| TargetSite |
Získá metodu, která vyvolá aktuální výjimku. (Zděděno od Exception) |
Metody
| Name | Description |
|---|---|
| Equals(Object) |
Určuje, zda je zadaný objekt roven aktuálnímu objektu. (Zděděno od Object) |
| GetBaseException() |
Při přepsání v odvozené třídě vrátí Exception to, že je původní příčinou jedné nebo více následných výjimek. (Zděděno od Exception) |
| GetHashCode() |
Slouží jako výchozí funkce hash. (Zděděno od Object) |
| GetObjectData(SerializationInfo, StreamingContext) |
Zastaralé.
Při přepsání v odvozené třídě nastaví SerializationInfo s informacemi o výjimce. (Zděděno od Exception) |
| GetType() |
Získá typ modulu runtime aktuální instance. (Zděděno od Exception) |
| MemberwiseClone() |
Vytvoří mělkou kopii aktuálního Object. (Zděděno od Object) |
| ToString() |
Vytvoří a vrátí řetězcovou reprezentaci aktuální výjimky. (Zděděno od Exception) |
Událost
| Name | Description |
|---|---|
| SerializeObjectState |
Zastaralé.
Nastane, když je výjimka serializována vytvořit objekt stavu výjimky, který obsahuje serializovaná data o výjimce. (Zděděno od Exception) |