I'm newbie at DotNet programming. I got a serious problem for me but I don't know why. I already used Dispose() method but "Out of memory" problem still occurs. At about first 30 times, everything works perfectly. Then, Out of memory happens. Furthermore, the images is from 13-16Mb. This is my code:
private void advanBtn_Click(object sender, EventArgs e)
{
InvertFunction();
}
private void InverFunction()
{
Bitmap bm = new Bitmap(imgBox.Image); // Out of memory
Image<Gray, byte> EmguImage = new Image<Gray, byte>(bm);
EmguImage = EmguImage.Not();
imgBox.Image.Dispose();
imgBox.Image = EmguImage.Bitmap;
bm.Dispose();
EmguImage.Dispose();
}
Try the suggestion in their documentation.
The time of when garbage collector decides to dispose the image is not
guaranteed. When working with large image, it is recommend to call the
Dispose() method to explicitly release the object. Alternatively, use
the using keyword in C# to limit the scope of the image
using (Bitmap bm = new Bitmap(imgBox.Image))
{
using (Image<Gray, Single> image = new Image<Gray, Single>(bm))
{
EmguImage = EmguImage.Not();
imgBox.Image.Dispose();
imgBox.Image = EmguImage.Bitmap;
}
}
As a last resort you can try forcing garbage collection. BUT this is not recomended and should be used only if you have no other way.
GC.Collect();
I would suggest you to read about it before using it here.
It might not be applicable anymore, but there were some version of the CLR that definitely had bugs with the LOH, where images normally get allocated. Might want to check that topic. A workaround was to manually check, if there was enough coherent memory (for external memory allocation) before allocating, which is a bit of a pain to do in C#. Just suggesting that you might not do something wrong.
I also had the problems with using OpenCV/Emgu and used opencvsharp for some problems. It is a more direct wrapper where you have to be very careful about memory allocation. It has been some time though and I cannot really remember the exaxt problem. It had to do with memory allocation. It should also be fixed by now I think.
Ended up having both as a dependency and it doesn't help for having clean code.
Otherwise, try to use the using statement other answers are suggesting. It calls .Dispose() automatically and starting the GC right away. That way, your memory doesn't fragment as much. You can also write..
using(Image a, Image b, Image c, ...) {}
... as long as the object implement IDisposable
Related
This question already has answers here:
WPF CreateBitmapSourceFromHBitmap() memory leak
(6 answers)
Closed 3 years ago.
3 Overall Questions
Through trial and error of commenting out certain lines it is possible for someone to determine the line and/or function which is causing a memory leak. I have done this, however, using Visual Studio, I cannot figure out how to view how much memory each variable is taking up to find out which is causing a memory leak. That is my first question.
My second is what exactly are they, I have read many posts in the past about references to variables stopping the GC and so on, but I really need someone to explain a bit simpler, because that just doesn't make sense to me. And I am sure many others feel the same way.
Lastly, how do you stop them, I have seen many articles on "unsubscribing" to events and such, but none of them seem to apply to me so none of those techniques work to solve this memory leak. I want to know a more complete way of preventing them which I am sure can be easily understood if I knew what they actually are.
Personal Question
This is one of those "my code is not working" questions. But wait... don't rage yet. My code has a memory leak however, from my very limited knowledge of what they are, I do not understand how this is possible. The function with the memory leak does not have any lines where I add values to a variable (to make it have a larger size), and there are no local variables (which would be Garbage Collected at the end of the function but may not be and might cause memory leaks). My memory leak is very severe, it adds approximately a Gigabyte a minute of memory being used. By the way, it might be useful to know that I am using a WPF in my code, you may recognise the file name patterns: NormalUI.xaml, NormalUI.xaml.cs, Program.cs.
I did not attach my full code, this is because there is no need and I am not lazy. I have made sure that I simplified my code (removed stuff) as much as I could while keeping the error present. This is also so that anybody experiencing the same problem can easily look at this answer and fix their own code.
Here is an image of the quite scary memory leak:
Simplified Code - NormalUI.xaml
<Image x:Name="Map"/>
Simplified Code - NormalUI.xaml.cs
public NormalUI()
{
// Setup some variables
// Start the timer to continually update the UI
System.Timers.Timer EverythingUpdaterTimer = new System.Timers.Timer();
EverythingUpdaterTimer.Elapsed += new ElapsedEventHandler(UpdateEverything);
EverythingUpdaterTimer.Interval = 100; // this has a memory leak
EverythingUpdaterTimer.Enabled = true;
InitializeComponent();
}
public void UpdateEverything(object source, ElapsedEventArgs e) // THIS FUNCTION CALLS THE FUNCTION WITH THE MEMORY LEAK (I THINK(
{
try // Statistics and map (won't work at the start before they have been declared... since this is a timer)
{
Dispatcher.Invoke(() => // Because this is a separate "thread"... I think...
{
// Update the map (height and width in the case of a load)
Map.Height = MAP_HEIGHT;
Map.Width = MAP_WIDTH;
Map.Source = Program.CalculateMap();
});
}
catch
{
Program.Log("Couldn't update general UI information");
}
}
Simplified Code - Program.cs
public static ImageSource CalculateMap()
{
/* This function is responsible for creating the map. The map is actually one large
* picture, but this function gets each individual smaller image (icon) and essentially
* "squashes" the images together to make the larger map. This function is used every
* single turn to update what the map looks like.
*/
List<List<Image>> map = new List<List<Image>>(world.rows);
// Create the empty world
for (int r = 0; r < world.rows; r++)
{
map.Add(new List<Image>(world.cols)); // Add images to list
for (int c = 0; c < world.cols; c++)
{
map[r].Add(EMPTY_ICON); // Add images to list
}
}
// Create the bitmap and convert it into a form which can be edited
Bitmap bitmapMap = new Bitmap(world.rows * ICON_WIDTH, world.cols * ICON_HEIGHT); // Get it? bitmapMap... bitMap...
Graphics g = Graphics.FromImage(bitmapMap);
// Add images to the bitmap
for (int r = 0; r < world.rows; r++)
{
for (int c = 0; c < world.cols; c++)
{
g.DrawImage(map[r][c], (c) * ICON_WIDTH, (r) * ICON_HEIGHT, ICON_WIDTH, ICON_HEIGHT);
}
}
// Convert it to a form usable by WPF (ImageSource).
ImageSource imageSourceMap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bitmapMap.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
// Return the new ImageSource.
return imageSourceMap;
}
I would very much appreciate an answer to my personal question... as well as the overall question.
The only objects that requires disposing are non-.NET objects. If the underlying O/S requires something like CloseHandle (or similar) to free up memory, then you will need to dispose that object in .NET code.
If any .NET classes implement IDisposable you MUST call .Dispose().
You can use tools such as the code analyser built into VS to point out where objects have a Dispose, but you aren't calling it.
Since I had a really nasty problem with an not too obvious unmanaged resource last month, I got a little hypernervous regarding memory leaking problems.
I was just coding on a very simple test app with a button with two different pictures on it and noticed I am not quite sure if I have a "problem" here or not...
If I have 2 picture resources Pic1 and Pic2 and an ImageButton-Object, which is just some object inherited from UserControl and with a changed OnPaint:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//stuff
if (this.keyStatus))
{ this.imageButton.DefaultImage = Resource1.Pic1; }
else
{ this.imageButton.DefaultImage = Resource1.Pic2; }
e.Graphics.DrawImage(this.defaultImage, this.ClientRectangle);
}
Beside OnPaint not being a good place for assigning DefaultImage (its just here to show you what I mean in a short piece of code), I am just assinging a reference to my precompiled resource here, am I? I am not creating a copy as I would if I would call it with new Bitmap(Resource1.Pic1).
So if I change keyStatus every 5 seconds, I would have a very annoying picture on my screen with a lot of changing, but no problems that the picture changing or turning it invisible from time to time leaks memory. Correct?
Thanks a lot!
How object references work
Say you have a random object. The object is a class type (not a value type) and not IDisposable. Basically that means the following:
// y is some object
var x = y;
Now, x doesn't copy all the data from y, but simply makes a new reference to the contents of y. Simple.
To ensure that there won't be memory leaks, the GC keeps track of all objects and (periodically) checks which objects are reachable. If an object is still reachable, it won't be deleted - if it's not, it will be removed.
And then there was unmanaged code
As long as you stick to managed code, everything is fine. The moment you run into unmanaged code (say: GDI+, which is the native counterpart of a lot of System.Drawing stuff) you need to do extra book-keeping to get rid of the code. After all, the .NET runtime doesn't know much about the unmanaged data - it merely knows that there is a pointer. Therefore, the GC will cleanup the pointer, but not the data -- which would result in memory leaks.
Therefore, the guys from .NET added IDisposable. By implementing IDisposable, you can implement extra (unmanaged) cleanup, such as releasing unmanaged memory, closing files, closing sockets, etc.
Now, the GC knows about finalizers, which are implemented as part of the Disposable pattern (details: https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx ). However, you usually don't want to wait for a GC run to clean up unmanaged resources. So, it's generally a good idea to call Dispose() when an object can be cleaned up and has unmanaged resources.
As is the case with System.Drawing.Bitmap, which implements IDisposable.
In most cases, you can simply wrap IDisposable in a using statement, which will call 'Dispose()' for you in a nice try/finally clause. e.g.:
using (var myBitmap = new Bitmap(...))
{
// use myBitmap
}
// myBitmap including all resources are gone.
What about resource bitmaps
#HansPassant pointed out that resource bitmaps generate a new Bitmap every time you access a bitmap property. This basically means that the bitmaps are copied and need to be disposed.
In other words:
// Free the old bitmap if it exists:
if (this.imageButton.DefaultImage != null)
{
this.imageButton.DefaultImage.Dispose();
this.imageButton.DefaultImage = null;
}
// assign new imageButton.DefaultImage
So, this solves the memory leak, but will give you a lot of data that is copied around.
If you don't want to dispose
Here comes the part why I was surprised by the remark from Hans :) Basically you assign a Bitmap to a button every time, so you don't want to copy the data over and over again - that makes little sense.
Therefore, you might get the idea to wrap the resource into a 'static' container and simply don't deallocate it at all:
static Bitmap myPic1 = Resource1.Pic1;
static Bitmap myPic2 = Resource1.Pic2;
...
if (this.keyStatus))
{
this.imageButton.DefaultImage = myPic1;
}
else
{
this.imageButton.DefaultImage = myPic2;
}
This works, but will give you issues if you at some point decide to generate images as well. To illustrate, say we change the code like this::
if (this.keyStatus))
{
this.imageButton.DefaultImage = myPic1; // #1 don't dispose
}
else
{
Bitmap myPic3 = CreateFancyBitmap(); // #2 do dispose
this.imageButton.DefaultImage = myPic3;
}
Now, the issue here is with the combination. myPic1 is a static object and shouldn't be disposed. On the other hand, myPic3 is not, and should be disposed. If you do call Dispose(), you'll get a nasty exception at #1, because the data is no longer there. There's no proper way to distinguish the two.
I swear I knew the answer to this one but I forgot.
I have this function. It loads bitmaps and draws them. it can be called in rapid succession. After about 300 or so bitmaps the application crashes with a System.OutOfMemoryException.
Please tell me what am I doing wrong again :)
private void PaintPicture()
{
string FullPath = Global.RunttimePath + EditType.FilePath;
if (File.Exists(FullPath))
{
Image i = Image.FromFile(FullPath);
//DrawImage(i, pnlPicture, pbColor.BackColor); //I disabled this so the problem is not here
i.Dispose();
//GC.Collect(); //I know I know... I should never call GC. So disabled it :)
}
else
{
//DrawImage(Properties.Resources.Fail800, pnlPicture, Color.White, true);
}
}
According to the documentation of Image.FromFile you can get an OutOfMemoryException if the bitmap is in an unknown format. Make sure your application can safely load all images you're trying to use and see if it always crashes on the same image.
If it's always the same image then you can try re-saving the image in a supported pixel format (using Photoshop or Paint.Net or some other free tool) - this should fix the particular image that breaks your application.
Also, add an exception handler around your drawing logic to make sure your application doesn't crash when it runs into a bad image - GDI+ only supports a relatively low number of image formats.
To verify if you're actually running out of memory (that is, if there is a leak), monitor memory use while your application is running. If you see signs of a memory leak, your problem is likely elsewhere.
Edit:
Read these questions / answers for advice about using Image.FromStream instead of FromFile() - doing so avoids locking the file for a long time:
File.Delete failing when Image.FromFile was called prior it, despite making copy of loaded image and destroying original one
out of memory Image.FromFile
This likely won't resolve your problem, but the Image class implements IDisposable. That means you can wrap it in a USING statement, which causes the objects inside to go out of scope faster/less objects surviving to L2 garbage collection (it shouldn't make a difference between wrapping things in a using vs. calling dispose, but we found through memory profiling that it actually does).
if (File.Exists(FullPath))
{
using(Image i = Image.FromFile(FullPath))
{
DrawImage(i, pnlPicture, pbColor.BackColor); //I disabled this so the problem is not here
//GC.Collect(); //I know I know... I should never call GC. So disabled it :)
}
}
else
{
//DrawImage(Properties.Resources.Fail800, pnlPicture, Color.White, true);
}
}
There appears to be a memory leak with WriteableBitmaps when writing to the backbuffer directly and using the AddDirtyRect function multiple times within a single Lock/Unlock. The rectangles need to define different regions within the bitmap. The memory will then leak when you try to discard the WriteableBitmap.
You can recreate it by inserting the following code into a new WPF application. When the application starts, resize the window to create new WriteableBitmaps and watch the memory rise.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Image m = new Image();
m.Stretch = Stretch.Fill;
this.Content = m;
this.SizeChanged += OnSizeChanged;
}
private void OnSizeChanged(object sender, SizeChangedEventArgs args)
{
WriteableBitmap bm = new WriteableBitmap((int)args.NewSize.Width, (int)args.NewSize.Height, 96, 96, PixelFormats.Bgra32, null);
bm.Lock();
bm.AddDirtyRect(new Int32Rect(1, 1, 1, 1));
bm.AddDirtyRect(new Int32Rect(2, 2, 1, 1));
bm.Unlock();
((Image)this.Content).Source = bm;
}
}
We need to be able to discard the bitmap so keeping the same one around and reusing it is not an option. We could also not write to the backbuffer directly and instead use WritableBitmap.WritePixels() but it's slower and speed is an issue.
UPDATE:
I've tested the WritePixels method and it leaks all the same. It may be an issue of calling too many writes too quickly in different regions.
We've contacted Microsoft on this issue and it appears to be a problem with the underlying c++ library backing WPF. We haven't been given an promise of when (or if) a fix will come but it is still a bug as of .NET 4.5.1.
There are currently only two ways we have found to work around this problem and they are mutually exclusive. You can either:
Never dirty any subregion of the bitmap, only dirty the full bitmap
The problem with this method is performance. You can try to counteract this by making your bitmaps smaller but there likely many situations where this isn't possible.
Never discard your bitmap
If you're going to dirty multiple subsections of the bitmap then you must ensure it will never be garbage collected unless you're about to close the application. This comes with it's own host of problems as you have to make sure the bitmap is large enough the first time you create it. If users are allowed to resize the window then you'll have to make it fit the entire desktop, but even this is problematic as users can change their desktop resolution or add/remove monitors meaning you'll either have to leak memory or not have enough bitmap to cover the entire possible size of the window.
Hopefully Microsoft will release a fix for this in the future but for the mean time be very careful with WriteableBitmap as it's very prone to leaking memory.
I have written some code to retrieve frames from a camera, along with information obtained from these frames, and to display them on a form.
All the data that I get is unmanaged as it comes form a library of my own written in c++ and working with OpenCv.
I prefer getting all the data at once with a single function call and not using a wrapper to OpenCv that would PInvoke several times to get the same result. Furthermore for me the code is easier to maintain and I have much more control on everything that is going on and I have many other reason to prefer this approach.
Everything is ok, (seemingly) perfectly working and I’m happy, but… there is something I would like to understand better with your help.
At a certain point I create a bitmap with the unmanaged pixel data with the method
public Bitmap(int width,int height,int stride,PixelFormat format, IntPtr scan0);
My question are the following (I have some idea, but just tell me if I’m right) :
1) I don’t release the data pointed by scan0 as I think that, once the data is owned by the bitmap object, it will do the job for me via its Garbage Collection. Am I right?
2) I don’t like the fact that a new instance of bitmap is created and allocated every time (apart from the pixel data), but I suppose that there is no better way of getting a Bitmap out of unmanaged data.
3) I think that there is no need to tell the Garbage Collector that there is a big amount of data to clean up with GC.AddMemoryPressure(…) as it knows it, estimating from the information provided with the initialization.
EDIT
I've found on the documentation
The caller is responsible for allocating and freeing the block of memory specified by the scan0 parameter. However, the memory should not be released until the related Bitmap is released.
The only way to do this is that the Bitmap object created in such a way leaves the data untouched and doesn't change its position in memory.
1) I don’t release the data pointed by scan0 as I think that, once the
data is owned by the bitmap object, it will do the job for me via its
Garbage Collection. Am I right?
No, the garbage collector knows nothing about the object, which you've initialized on the unmanaged side, that is why it is unmanaged. So you have to call delete in the unmanaged code to release the allocated memory.
2) I don’t like the fact that a new instance of bitmap is created and
allocated every time (apart from the pixel data), but I suppose that
there is no better way of getting a Bitmap out of unmanaged data.
There is a way and a keyword is unsafe. You can run the c++ code inside of the unsafe block, but you must allow this in the c# project settings. So you can reuse every pixel of once initialized bitmap
unsafe
{
byte stlThres = 115;
Bitmap myBmp = ...; // init the bitmap
var data = myBmp.LockBits(new Rectangle(0, 0, myBmp.Width, myBmp.Height), ImageLockMode.WriteOnly, myBmp.PixelFormat);
for (int y = 0; y < data.Height; y++)
{
byte* row = (byte*)data.Scan0 + (y * data.Stride);
//...
}
3) I think that there is no need to tell the Garbage Collector that
there is a big amount of data to clean up with GC.AddMemoryPressure(…)
as it knows it, estimating from the information provided with the
initialization.
If you created a managed Bitmap object (with new), it will be released automatically after it gets out of scope or will not be referenced any longer.