Выдано исключение типа system outofmemoryexception что это
Перейти к содержимому

Выдано исключение типа system outofmemoryexception что это

  • автор:

Debugging System.OutOfMemoryException using .NET tools

Welcome to the second part of the series about Debugging common .NET exceptions. The series is my attempt to demystify common exceptions as well as to provide actual help fixing each exception.

Debugging System.OutOfMemoryException using .NET tools

In this post, I take a look at one of the more tricky exceptions to fix: System.OutOfMemoryException. As the name suggests, the exception is thrown when a .NET application runs out of memory. There are a lot of blog posts out there, trying to explain why this exception occurs, but most of them are simply rewrites of the documentation on MSDN: System.OutOfMemoryException Class. In the MSDN article, two different causes of the OutOfMemoryException are presented:

  1. Attempting to expand a StringBuilder object beyond the length defined by its StringBuilder.MaxCapacity property. This type of error typically has this message attached: «Insufficient memory to continue the execution of the program.»
  2. The common language runtime (CLR) cannot allocate enough contiguous memory.

In my past 13 years as a .NET developer, I haven’t experienced the first problem, why I won’t bother spending too much time on it. In short, doing something like this will cause a System.OutOfMemoryException :

Why? Well, we define a new StringBuilder with a max capacity of one character and then try to insert two characters.

With that out of the way, let’s talk about why you are probably experiencing the exception: because the CLR cannot allocate the memory that your program is requesting. To translate this into something that your Mom would understand, your application is using more resources than available.

.NET programs often use a lot of memory. The memory management in .NET is based on garbage collection, which means that you don’t need to tell the framework when to clean up. When .NET detects that an object is no longer needed, it is marked for deletion and deleted next time the garbage collector is running. This also means that an OutOfMemoryException doesn’t always equal a problem. 32-bit processes have 2 GB of virtual memory available, and 64-bit processes have up to 8 TB. Always make sure to compile your app to 64-bit if running on a 64-bit OS (it probably does that already). If you’re interested in more details about this subject, I recommend this article from Eric Lippert, a former Microsoft employee working on the C# compiler: “Out Of Memory” Does Not Refer to Physical Memory. It’s important to distinguish between heavy memory usage and a memory leak. The first scenario can be acceptable, while the second always requires debugging.

Would your users appreciate fewer errors?

To start debugging the OutOfMemoryException , I recommend you to look at your application either through the Task Manager or using perfmon.msc . Both tools can track the current memory consumption, but to get a better overview over time, perfmon is the best. When launched, right-click the graph area and click Add Counters. Expand the .NET CLR Memory node and click # Total committed Bytes. Finally, select the process you want to monitor in the Instances of selected object list and click the OK button.

For the rest of this post, I will use and modify a sample program, adding strings to a list:

In its current state, the program keeps adding strings to a list and every 10,000,000 times clear the list. When looking at the current memory usage in Perfmon, you’ll see the current picture:

Current memory usage in Perfmon

Garbage collection at its finest. Here, I’ve removed the call to list.Clear() :

We now get a completely other picture:

Allocating memory in Perfmon

The program keeps allocating memory, until a System.OutOfMemoryException is thrown.

The example illustrates how you can utilize Perfmon to monitor the state of your application. Like the chefs on TV, I cheated and made up an example for this post. In your case, you probably have no clue to what causes the extensive use of memory. Memory profilers to the rescue!

Unlike Task Manager and Perfmon, memory profilers are tools to help you find the root cause of a memory problem or memory leak. There a lot of useful tools out there like JetBrains dotMemory and ANTS Memory Profiler. For this post, I’ll use .NET Memory Profiler, which I have used heavily in the past. BTW, as an elmah.io customer, you will get a 20% discount on .NET Memory Profiler.

.NET Memory Profiler integrates nicely into Visual Studio, why profiling your application is available by clicking the new Profiler > Start Memory Profiler menu item. Running our sample from previously, we see a picture similar to that of Perfmon:

Memory allocation in Visual Studio

The picture looks pretty much like before. The process allocates more and more memory (the orange and red lines), and the process throws an exception. In the bottom, all objects allocated from the profiling sessions are shown and ordered allocations. Looking at the top rows is a good indicator of what is causing a leak.

In the simple example, it’s obvious that the strings added to the list if the problem. But most programs are more complex than just adding random strings to a list. This is where the snapshot feature available in .NET Memory Profiler (and other tools as well) shows its benefits. Snapshots are like restore points in Windows, a complete picture of the current memory usage. By clicking the Collect snapshot button while the process is running, you get a diff:

Diff memory usage in Visual Studio

Looking at the Live Instances > New column, it’s clear that someone is creating a lot of strings.

I don’t want this to be an ad for .NET Memory Profiler, so check out their documentation for the full picture of how to profile memory in your .NET programs. Also, make sure to check out the alternative products mentioned above. All of them have free trials, so try them out and pick your favorite.

I hope that this post has provided you with «a very particular set of skills» (sorry) to help you debug memory issues. Unfortunately, locating memory leaks can be extremely hard and requires some training and experience.

Also make sure to read the other posts in this series: Debugging common .NET exception.

C# : Out of Memory exception

Today my application threw an OutOfMemoryException . To me this was always almost impossible since I have 4GB RAM and a lot of virtual memory too. The error happened when I tried to add an existing collection to a new list.

To my understanding there isn’t much memory allocated here since the vehicles my new list should contain already exist inside the memory. I have to admit Vehicle is a very complex class and I tried to add about 50.000 items to the new list at once. But since all Vehicle s in the application come from a database that is only 200MB in size, I have no idea what may cause an OutOfMemoryException at this point.

11 Answers 11

3 years old topic, but I found another working solution. If you’re sure you have enough free memory, running 64 bit OS and still getting exceptions, go to Project properties -> Build tab and be sure to set x64 as a Platform target .

enter image description here

  1. If you are running a 32 bit Windows, you won’t have all the 4GB accessible, only 2GB.
  2. Don’t forget that the underlying implementation of List is an array. If your memory is heavily fragmented, there may not be enough contiguous space to allocate your List , even though in total you have plenty of free memory.

Tudor's user avatar

.NET Framework 4.5 does not have a 2GB limitation for objects any more. Add these lines to App.config

and it will be possible to create very large objects without getting OutOfMemoryException

Please note it will work only on x64 OS’s!

Data stored in database compared to memory in your application is very different.

There isn’t a way to get the exact size of your object but you could do this:

After a certain amount of objects have been loaded and see how much your memory is changing as you load the list.

If it is the list that is causing the excessive memory usage then we can look at ways to minimize it. Such as why do you want 50,000 objects loaded into memory all at once in the first place. Wouldn’t it be best to call the DB as you require them?

If you take a look here: http://www.dotnetperls.com/array-memory you will also see that objects in .NET are greater than their actual data. A generic list is even more of a memory hog than an array. If you have a generic list inside your object then it will grow even faster.

OutOfMemoryException (on 32-bit machines) is just as often about Fragmentation as actual hard limits on memory — you’ll find lots about this, but here’s my first google hit briefly discussing it: http://blogs.msdn.com/b/joshwil/archive/2005/08/10/450202.aspx. (@Anthony Pegram is referring to the same problem in his comment above).

That said, there is one other possibility that comes to mind for your code above: As you’re using the «IEnumerable» constructor to the List, you may not giving the object any hints as to the size of the collection you’re passing to the List constructor. If the object you are passing is is not a collection (does not implement the ICollection interface), then behind-the-scenes the List implementation is going to need to grow several (or many) times, each time leaving behind a too-small array that needs to be garbage collected. The garbage collector probably won’t get to those discarded arrays fast enough, and you’ll get your error.

The simplest fix for this would be to use the List(int capacity) constructor to tell the framework what backing array size to allocate (even if you’re estimating and just guessing «50000» for example), and then use the AddRange(IEnumerable collection) method to actually populate your list.

So, simplest «Fix» if I’m right: replace

All the other comments and answers still apply in terms of overall design decisions — but this might be a quick fix.

Note (as @Alex commented below), this is only an issue if selectedVehicles is not an ICollection.

I know this is an old question but since none of the answers mentioned the large object heap, this might be of use to others who find this question .

Any memory allocation in .NET that is over 85,000 bytes comes from the large object heap (LOH) not the normal small object heap. Why does this matter? Because the large object heap is not compacted. Which means that the large object heap gets fragmented and in my experience this inevitably leads to out of memory errors.

In the original question the list has 50,000 items in it. Internally a list uses an array, and assuming 32 bit that requires 50,000 x 4bytes = 200,000 bytes (or double that if 64 bit). So that memory allocation is coming from the large object heap.

So what can you do about it?

If you are using a .net version prior to 4.5.1 then about all you can do about it is to be aware of the problem and try to avoid it. So, in this instance, instead of having a list of vehicles you could have a list of lists of vehicles, provided no list ever had more than about 18,000 elements in it. That can lead to some ugly code, but it is viable work around.

If you are using .net 4.5.1 or later then the behaviour of the garbage collector has changed subtly. If you add the following line where you are about to make large memory allocations:

it will force the garbage collector to compact the large object heap — next time only.

It might not be the best solution but the following has worked for me:

of course this only helps if you have the physical (or virtual) memory available.

Ошибка System.OutOfMemoryException

Ошибка System.OutOfMemoryException
Здравствуйте, есть программа в WinForms, работает с текстовиками. вытаскивает данные из одного.

Ошибка System.OutOfMemoryException
Получил вот такую ошибку. Зачем происходит такая ошибка?

Ошибка System.OutOfMemoryException — как обойти?
Добрый день. На данный момент в коде в 2-х местах встречаются подобные исключения, т.е. как я.

kolorotur, нифига себе. А это ссылка на любой объект занимает 4 байта?

Добавлено через 2 минуты

Сообщение от Siend

Разумеется. Если система 32-битная, то и ссылка занимает 32 бита (4 байта).

Сообщение от Siend

Сообщение от Siend

kolorotur, ну я не представляю другого варианта. разве что только работать с текстовыми документами, но это тоже бред)

Добавлено через 3 минуты
kolorotur, а вот такой вопрос — если писать не на c# а на чистом си, то в итоге при попытке объявить такой массив я столкнусь с той же проблемой? или там распределение памяти по другому происходит?

Сообщение от Siend

Поделитесь техзаданием — наверняка есть другое решение.

Да, на сях столкнетесь с тем же самым.

kolorotur, собственно вопрос можно сформулировать так:
нужно посчитать сколько раз буква встретилась на той или иной позиции периода в символьной последовательности. т.е.:
допустим наша исходная символьная последовательность была:
"ааабабвггд"
тогда для периода в 2 символа будет такая картина:
"аа аб аб вг гд"
а 3 1
б 1 1
в 1 0
г 1 1
д 0 1
для периода 3:
"ааа баб вгг д"
а 1 2 1
б 1 0 1
в 1 0 0
г 0 1 1
д 1 0 0

и т.д.
а теперь внимание:
длинна символьной последовательности может быть любой, в моем случае она порядка 600 символов.
периоды для которых нужно получить вот такие вот матрицы распределений от 2 до [n/2] где n — длина исходной символьной последовательности, т.е. от 2 до 300.
и собственно в качестве символов выступают буквы русского языка + пробел, итого 34 символа.
собственно единственная модификация вот к этому:

Management Studio System.OutOfMemoryException

I’m using Microsoft SQL Server 2012 and trying to run a simple query against it within Management Studio. I’m getting the following error (in SSMS, running on the server):

An error occurred while executing batch. Error message is: Exception of type ‘System.OutOfMemoryException’ was thrown.

The system has 24GB of RAM installed but looking in task manager the sqlservr.exe process is only using 2.9GB.

Is there a setting somewhere that is restricting its RAM usage?

6 Answers 6

This error indicates that Management Studio is running out of memory, not the SQL Server service. Even if you installed 64 bit SQL Server, the SQL Server Management Studio executable is a 32 bit application.

This is likely caused by the size of the result set that you are returning to Management Studio. Are you executing something like SELECT * FROM really_big_table? See http://support.microsoft.com/kb/2874903 for more.

Mike is right that the error message you’re receiving is from the Management Studio application itself, and not from SQL Server. It is the memory on your local workstation that has been exhausted, likely due to trying to pull 16 billion rows into the client application (rendering that much data in a grid is quite expensive in terms of memory, so try to limit your queries using TOP etc. — I don’t know what practical thing(s) you could possibly do with enough data to use up all of your local memory anyway).

But I do want to address another problem: using Task Manager to assess the amount of memory SQL Server is using. Don’t do this; it’s a bold-faced liar. Copying from this answer (your question is two-fold, so I can’t really close it as a duplicate):

You could NEVER, EVER trust Task Manager to tell you how much memory SQL Server is using. Stop using Task Manager for this, period. Use the performance counter — you can also query the performance counter using DMVs:

You could save that as a query shortcut in Tools > Options > Environment > Keyboard > Query Shortcuts, and get accurate results in a query window much faster than getting inaccurate results from Task Manager.

You can also check for memory pressure (and whether you can do anything about it) using these queries:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *