OutOfMemoryException Osztály
Definíció
Fontos
Egyes információk olyan, kiadás előtti termékekre vonatkoznak, amelyek a kiadásig még jelentősen módosulhatnak. A Microsoft nem vállal kifejezett vagy törvényi garanciát az itt megjelenő információért.
A kivétel, amely akkor merül fel, ha nincs elegendő memória a program végrehajtásának folytatásához.
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
- Öröklődés
- Öröklődés
- Származtatott
- Attribútumok
Megjegyzések
OutOfMemoryException A HRESULT COR_E_OUTOFMEMORYfüggvényt használja, amelynek értéke 0x8007000E.
A OutOfMemoryException példány kezdeti tulajdonságainak listájáért tekintse meg a OutOfMemoryException konstruktorokat.
Note
Az örökölt Data tulajdonság értéke mindig null.
A OutOfMemoryException kivételnek két fő oka van:
Megpróbál kibontani egy objektumot StringBuilder a tulajdonsága által StringBuilder.MaxCapacity meghatározott hosszon túl.
A közös nyelvi futtatókörnyezet nem tud elegendő összefüggő memóriát lefoglalni egy művelet sikeres végrehajtásához. Ezt a kivételt bármely olyan tulajdonság-hozzárendelés vagy metódushívás okozhatja, amely memóriafoglalást igényel. A kivétel okával OutOfMemoryException kapcsolatos további információkért tekintse meg a "Memóriakihasználtság" című blogbejegyzést, amely nem hivatkozik a fizikai memóriára.
Ez a OutOfMemoryException kivételtípus katasztrofális hibát jelez. Ha úgy dönt, hogy kezeli a kivételt, olyan blokkot
catchkell tartalmaznia, amely meghívja a metódust az Environment.FailFast alkalmazás leállítására, és adjon hozzá egy bejegyzést a rendszer eseménynaplójához, ahogy az alábbi példa is teszi.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...
Néhány feltétel, amely mellett a kivételt ki lehet dobni, és a kiküszöbölése érdekében végrehajtható műveletek közé tartoznak a következők:
A metódust StringBuilder.Insert hívja meg.
Megkísérli növelni egy objektum hosszát StringBuilder a tulajdonsága által StringBuilder.MaxCapacity megadott méreten túl. Az alábbi példa a OutOfMemoryException metódus hívása StringBuilder.Insert(Int32, String, Int32) által okozott kivételt mutatja be, amikor a példa olyan sztringet próbál beszúrni, amely miatt az objektum tulajdonsága Length meghaladja a maximális kapacitást.
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.
A hiba elhárításához tegye az alábbiak egyikét:
Cserélje le a StringBuilder.StringBuilder(Int32, Int32) konstruktor hívását bármely más StringBuilder konstruktor túlterhelésére. Az objektum maximális kapacitása StringBuilder az alapértelmezett értékre lesz állítva, azaz .Int32.MaxValue
Hívja meg a StringBuilder.StringBuilder(Int32, Int32) konstruktort olyan
maxCapacityértékkel, amely elég nagy ahhoz, hogy elférjen az StringBuilder objektum esetleges bővítései.
Az alkalmazás 32 bites folyamatként fut.
A 32 bites folyamatok legfeljebb 2 GB virtuális felhasználói módú memóriát foglalhatnak le 32 bites rendszereken, és 4 GB virtuális felhasználói módú memóriát 64 bites rendszereken. Ez megnehezítheti, hogy a közös nyelvi futtatókörnyezet elegendő összefüggő memóriát foglaljon le, ha nagy foglalásra van szükség. Ezzel szemben a 64 bites folyamatok akár 8 TB virtuális memóriát is lefoglalhatnak. A kivétel megoldásához újrafordítással célozhat meg egy 64 bites platformot. Az egyes platformok Visual Studio való megcélzásával kapcsolatos információkért lásd: Beállítás: Projektek konfigurálása célplatformokra.
Az alkalmazás nem felügyelt erőforrásokat szivárogtat ki
Bár a szemétgyűjtő képes felszabadítani a felügyelt típusok számára lefoglalt memóriát, nem kezeli a nem felügyelt erőforrásokhoz, például az operációsrendszer-leírókhoz (beleértve a fájlokhoz tartozó leírókat, a memórialeképezett fájlokat, a csöveket, a beállításkulcsokat és a várakozási fogópontokat) és a közvetlenül Windows API-hívások vagy a memórialefoglalási függvények, például malloc által lefoglalt memóriablokkokat. A nem felügyelt erőforrásokat használó típusok implementálják a IDisposable felületet.
Ha nem felügyelt erőforrásokat használó típust használ, mindenképpen hívja meg a metódust IDisposable.Dispose , amikor befejezte a használatát. (Egyes típusok egy Close metódussal azonos metódust Dispose is implementálnak.) További információt az IDisposable-t implementáló objektumok használata című témakörben talál.
Ha olyan típust hozott létre, amely nem felügyelt erőforrásokat használ, győződjön meg arról, hogy implementálta az Elidegenítési mintát, és szükség esetén adott meg egy véglegesítőt. További információ: Implementing a Dispose metódus és Object.Finalize.
Nagy tömböt próbál létrehozni egy 64 bites folyamatban
Alapértelmezés szerint a .NET Framework közös nyelvi futtatókörnyezete nem engedélyezi a 2 GB-ot meghaladó méretű objektumok használatát. Az alapértelmezett beállítás felülbírálásához a <gcAllowVeryLargeObjects konfigurációs> fájlbeállításával engedélyezheti a 2 GB-nál nagyobb méretű tömböket. A .NET Core-on alapértelmezés szerint engedélyezve van a 2 GB-nál nagyobb tömbök támogatása.
Nagyon nagy adatkészletekkel (például tömbökkel, gyűjteményekkel vagy adatbázis-adatkészletekkel) dolgozik a memóriában.
Ha a memóriában található adatstruktúrák vagy adathalmazok olyan nagyok lesznek, hogy a közös nyelvi futtatókörnyezet nem tud elegendő összefüggő memóriát lefoglalni számukra, kivétel OutOfMemoryException jön létre.
A OutOfMemoryException kivételek elkerülése érdekében módosítania kell az alkalmazást, hogy kevesebb adat legyen a memóriában, vagy hogy az adatok olyan szegmensekre legyenek felosztva, amelyek kisebb memóriakiosztást igényelnek. Például:
Ha az összes adatot egy adatbázisból kéri le, majd szűri az alkalmazásban a kiszolgálóra való utazások minimalizálása érdekében, módosítsa a lekérdezéseket, hogy csak az alkalmazás által igényelt adathalmazt adja vissza. Nagy táblák használatakor több lekérdezés is majdnem mindig hatékonyabb, mint az összes adat beolvasása egyetlen táblában, majd annak manipulálása.
Ha dinamikusan létrehozott lekérdezéseket hajt végre, győződjön meg arról, hogy a lekérdezés által visszaadott rekordok száma korlátozott.
Ha nagy tömböket vagy más olyan gyűjteményobjektumokat használ, amelyek mérete kivételt OutOfMemoryException eredményez, az alkalmazást úgy kell módosítania, hogy az adatokat alhalmazokban dolgozza fel, nem pedig egyszerre.
Az alábbi példa egy 200 millió lebegőpontos értékből álló tömböt kap, majd kiszámítja a középértéküket. A példa kimenete azt mutatja, hogy mivel a példa a teljes tömböt a memóriában tárolja, mielőtt kiszámítja a középértéket, a rendszer eldob egy OutOfMemoryException értéket.
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.
Az alábbi példa kiküszöböli a OutOfMemoryException kivételt azáltal, hogy a bejövő adatokat úgy dolgozza fel, hogy nem tárolja a teljes adatkészletet a memóriában, és szükség esetén szerializálja az adatokat egy fájlba a további feldolgozás engedélyezéséhez (ezeket a sorokat a példában megjegyzésként fűzik hozzá, mivel ebben az esetben egy 1 GB-nál nagyobb méretű fájlt hoznak létre), és visszaadják a számított középértéket és az esetek számát a hívási rutinnak.
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
Ismétlődően összefűz nagy sztringeket.
Mivel a sztringek nem módosíthatók, minden sztringösszefűzési művelet új sztringet hoz létre. A kis sztringek vagy kis számú összefűzési művelet hatása elhanyagolható. Nagy sztringek vagy nagyon sok összefűzési művelet esetén azonban a sztringösszefűzés sok memóriafoglaláshoz és memóriatöredezettséghez, gyenge teljesítményhez és esetleg OutOfMemoryException kivételekhez vezethet.
Nagy sztringek összefűzésekor vagy nagy számú összefűzési művelet végrehajtásakor az StringBuilder osztályt kell használnia az String osztály helyett. Ha befejezte a sztring manipulálását, konvertálja a StringBuilder példányt sztringgé a StringBuilder.ToString metódus meghívásával.
Sok objektumot rögzíthet a memóriában.
Ha hosszú ideig sok objektumot rögzít a memóriában, az megnehezítheti a szemétgyűjtő számára az egyidejű memóriablokkok lefoglalását. Ha nagy számú objektumot rögzített a memóriában, például a fixed C# utasítással vagy a GCHandle.Alloc(Object, GCHandleType) metódus leírótípussal GCHandleType.Pinnedvaló meghívásával, a kivétel elhárításához OutOfMemoryException az alábbiakat teheti meg.
Annak kiértékelése, hogy az egyes objektumokat valóban rögzíteni kell-e,
Győződjön meg arról, hogy az egyes objektumok a lehető leghamarabb nem lesznek rögzítve.
Győződjön meg arról, hogy a GCHandle.Alloc(Object, GCHandleType) memória rögzítésére szolgáló metódus minden hívása rendelkezik a metódusnak megfelelő hívással a GCHandle.Free memória rögzítésének feloldásához.
Az alábbi Microsoft köztes (MSIL) utasítások OutOfMemoryException kivételt eredményeznek:
Konstruktorok
| Name | Description |
|---|---|
| OutOfMemoryException() |
Inicializálja a OutOfMemoryException osztály új példányát. |
| OutOfMemoryException(SerializationInfo, StreamingContext) |
Elavult.
Inicializálja az OutOfMemoryException osztály új példányát szerializált adatokkal. |
| OutOfMemoryException(String, Exception) |
Inicializálja az OutOfMemoryException osztály új példányát egy megadott hibaüzenettel és a kivétel okaként szolgáló belső kivételre mutató hivatkozással. |
| OutOfMemoryException(String) |
Inicializálja az OutOfMemoryException osztály új példányát egy megadott hibaüzenettel. |
Tulajdonságok
| Name | Description |
|---|---|
| Data |
Lekéri a kulcs-/érték párok gyűjteményét, amelyek további, felhasználó által definiált információkat biztosítanak a kivételről. (Öröklődés forrása Exception) |
| HelpLink |
Lekéri vagy beállítja a kivételhez társított súgófájlra mutató hivatkozást. (Öröklődés forrása Exception) |
| HResult |
Lekéri vagy beállítja a HRESULT-ot, egy kódolt numerikus értéket, amely egy adott kivételhez van hozzárendelve. (Öröklődés forrása Exception) |
| InnerException |
Lekéri az Exception aktuális kivételt okozó példányt. (Öröklődés forrása Exception) |
| Message |
Az aktuális kivételt leíró üzenet jelenik meg. (Öröklődés forrása Exception) |
| Source |
Lekéri vagy beállítja az alkalmazás vagy a hibát okozó objektum nevét. (Öröklődés forrása Exception) |
| StackTrace |
Lekéri a hívásverem közvetlen kereteinek sztringképét. (Öröklődés forrása Exception) |
| TargetSite |
Lekéri az aktuális kivételt okozó metódust. (Öröklődés forrása Exception) |
Metódusok
| Name | Description |
|---|---|
| Equals(Object) |
Meghatározza, hogy a megadott objektum egyenlő-e az aktuális objektummal. (Öröklődés forrása Object) |
| GetBaseException() |
Ha egy származtatott osztály felül van bírálva, egy Exception vagy több későbbi kivétel kiváltó okát adja vissza. (Öröklődés forrása Exception) |
| GetHashCode() |
Ez az alapértelmezett kivonatoló függvény. (Öröklődés forrása Object) |
| GetObjectData(SerializationInfo, StreamingContext) |
Elavult.
Ha felül van bírálva egy származtatott osztályban, a SerializationInfo kivétel adatait adja meg. (Öröklődés forrása Exception) |
| GetType() |
Lekéri az aktuális példány futtatókörnyezeti típusát. (Öröklődés forrása Exception) |
| MemberwiseClone() |
Az aktuális Objectpéldány sekély másolatát hozza létre. (Öröklődés forrása Object) |
| ToString() |
Létrehozza és visszaadja az aktuális kivétel sztring-ábrázolását. (Öröklődés forrása Exception) |
esemény
| Name | Description |
|---|---|
| SerializeObjectState |
Elavult.
Akkor fordul elő, ha a kivétel szerializálva van egy kivételállapot-objektum létrehozásához, amely szerializált adatokat tartalmaz a kivételről. (Öröklődés forrása Exception) |