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 использует HRESULT COR_E_OUTOFMEMORY, который имеет значение 0x8007000E.
Список начальных значений свойств для экземпляра OutOfMemoryExceptionсм. в конструкторах OutOfMemoryException.
Замечание
Значение унаследованного Data свойства всегда null.
Исключение OutOfMemoryException имеет две основные причины:
Вы пытаетесь развернуть StringBuilder объект за пределами длины, определенной его StringBuilder.MaxCapacity свойством.
Среда CLR не может выделить достаточно непрерывной памяти для успешного выполнения операции. Это исключение может быть вызвано любым вызовом назначения свойств или метода, требующим выделения памяти. Дополнительные сведения о причине 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...
Некоторые условия, при которых создается исключение, и действия, которые можно предпринять для устранения, включают следующие:
Вызывается StringBuilder.Insert метод.
Вы пытаетесь увеличить длину объекта за пределы размера, указанного StringBuilder его StringBuilder.MaxCapacity свойством. В следующем примере показано OutOfMemoryException исключение, вызванное вызовом StringBuilder.Insert(Int32, String, Int32) метода, когда пример пытается вставить строку, которая приведет к превышению максимальной емкости свойства объекта Length .
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.
Чтобы устранить ошибку, выполните одно из следующих действий:
Замените вызов StringBuilder.StringBuilder(Int32, Int32) конструктора вызовом любой другой StringBuilder перегрузки конструктора. Максимальная емкость StringBuilder объекта будет задана в значение по умолчанию.Int32.MaxValue
StringBuilder.StringBuilder(Int32, Int32) Вызовите конструктор со
maxCapacityзначением, достаточно большим для размещения любых расширений к объектуStringBuilder.
Приложение выполняется как 32-разрядный процесс.
32-разрядные процессы могут выделять не более 2 ГБ памяти в режиме виртуального пользователя в 32-разрядных системах и 4 ГБ памяти в режиме виртуального пользователя в 64-разрядных системах. Это может сделать его более сложным для среды CLR, чтобы выделить достаточную непрерывную память, если требуется большое выделение. В отличие от этого, 64-разрядные процессы могут выделять до 8TB виртуальной памяти. Чтобы устранить это исключение, перекомпилируйте приложение для целевой 64-разрядной платформы. Сведения о целевых платформах в Visual Studio см. в статье "Практическое руководство. Настройка проектов на целевые платформы".
Ваше приложение утечки неуправляемых ресурсов
Хотя сборщик мусора может освободить память, выделенную для управляемых типов, не управляет памятью, выделенной для неуправляемых ресурсов, таких как дескрипторы операционной системы (включая дескрипторы файлов, сопоставленные с памятью файлы, каналы, разделы реестра и дескрипторы ожидания), а также блоки памяти, выделенные непосредственно вызовами API Windows или вызовами функций выделения памяти, например malloc. Типы, использующие неуправляемые IDisposable ресурсы, реализуют интерфейс.
Если вы используете тип, использующий неуправляемые ресурсы, необходимо вызвать его IDisposable.Dispose метод после завершения его использования. (Некоторые типы также реализуют метод, идентичный Close в функции методу Dispose .) Дополнительные сведения см. в разделе "Использование объектов, реализующих IDisposable ".
Если вы создали тип, использующий неуправляемые ресурсы, убедитесь, что вы реализовали шаблон Dispose и при необходимости предоставили метод завершения. Дополнительные сведения см. в разделе "Реализация метода Dispose " и Object.Finalize.
Вы пытаетесь создать большой массив в 64-разрядном процессе
По умолчанию среда CLR в .NET Framework не разрешает отдельные объекты, размер которых превышает 2 ГБ. Чтобы переопределить этот параметр по умолчанию, можно использовать <параметр файла конфигурации gcAllowVeryLargeObjects> , чтобы включить массивы, общий размер которых превышает 2 ГБ. В .NET Core поддержка массивов размером более 2 ГБ включена по умолчанию.
Вы работаете с очень большими наборами данных (например, массивами, коллекциями или наборами данных базы данных) в памяти.
Когда структуры данных или наборы данных, находящиеся в памяти, становятся настолько большими, что среда CLR не может выделить достаточно непрерывную память для них, OutOfMemoryException результаты исключения.
Чтобы предотвратить OutOfMemoryException исключения, необходимо изменить приложение таким образом, чтобы меньше данных было резидентом в памяти, или данные делятся на сегменты, требующие выделения памяти меньшего размера. Рассмотрим пример.
Если вы извлекаете все данные из базы данных, а затем фильтруете их в приложении, чтобы свести к минимуму поездки на сервер, необходимо изменить запросы, чтобы вернуть только подмножество данных, необходимых приложению. При работе с большими таблицами несколько запросов почти всегда эффективнее, чем получение всех данных в одной таблице, а затем управление ими.
Если вы выполняете запросы, которые пользователи создают динамически, убедитесь, что количество записей, возвращаемых запросом, ограничено.
Если вы используете большие массивы или другие объекты коллекции, размер которых приводит OutOfMemoryException к исключению, необходимо изменить приложение, чтобы работать с данными в подмножествах, а не работать с ним одновременно.
В следующем примере получается массив, состоящий из 200 миллионов значений с плавающей запятой, а затем вычисляет их среднее значение. Выходные данные из примера показывают, что, поскольку в примере хранится весь массив в памяти, прежде чем вычислять среднее значение, 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.
В следующем примере исключение устраняется OutOfMemoryException путем обработки входящих данных, не сохраняя весь набор данных в памяти, сериализуя данные в файл при необходимости, чтобы разрешить дальнейшую обработку (эти строки закомментированы в примере, так как в этом случае они создают файл, размер которого превышает 1 ГБ), а также возвращает вычисляемое среднее значение и количество случаев в вызывающей подпрограмме.
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 , исключений.
При объединении больших строк или выполнении большого количества операций объединения следует использовать StringBuilder класс вместо String класса. Завершив обработку строки, преобразуйте StringBuilder экземпляр в строку, вызвав StringBuilder.ToString метод.
Вы закрепляете большое количество объектов в памяти.
Закрепление большого количества объектов в памяти в течение длительных периодов может затруднить сборщик мусора выделить смежные блоки памяти. Если вы закрепляли большое количество объектов в памяти, например с помощью fixed инструкции в C# или путем вызова GCHandle.Alloc(Object, GCHandleType) метода с типом GCHandleType.Pinnedдескриптора, можно выполнить следующее, чтобы устранить OutOfMemoryException исключение.
Оцените, требуется ли закрепление каждого объекта.
Убедитесь, что каждый объект откреплен как можно скорее.
Убедитесь, что каждый вызов GCHandle.Alloc(Object, GCHandleType) метода для закрепления памяти имеет соответствующий вызов GCHandle.Free метода, чтобы открепить память.
Следующие промежуточные инструкции Майкрософт (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() |
При переопределении в производном классе возвращает Exception, которая является основной причиной одного или нескольких последующих исключений. (Унаследовано от Exception) |
| GetHashCode() |
Служит хэш-функцией по умолчанию. (Унаследовано от Object) |
| GetObjectData(SerializationInfo, StreamingContext) |
Устаревшие..
При переопределении в производном классе задает SerializationInfo с информацией об исключении. (Унаследовано от Exception) |
| GetType() |
Возвращает тип среды выполнения текущего экземпляра. (Унаследовано от Exception) |
| MemberwiseClone() |
Создает неглубокую копию текущей Object. (Унаследовано от Object) |
| ToString() |
Создает и возвращает строковое представление текущего исключения. (Унаследовано от Exception) |
События
| Имя | Описание |
|---|---|
| SerializeObjectState |
Устаревшие..
Происходит при сериализации исключения для создания объекта состояния исключения, содержащего сериализованные данные об исключении. (Унаследовано от Exception) |