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.