C
C#2y ago
Kevin Tran

❔ Memory Leakage for beginner

any tips or roadmaps for learning how to avoid or identify memory leakage issues in your code?
6 Replies
WTDawson9
WTDawson92y ago
Well, C# is good for automatically sorting memory leaking. But what I do is: - Run all of the different things in the program, wait for them to finish and see if it still uses the same amount of RAM or higher when it was running
V0FBU1VM
V0FBU1VM2y ago
C# takes care of Garbage Collection automatically. But it's also your job to write efficient code and in certain places dispose of things you no longer need.
sibber
sibber2y ago
garbage collection doesnt mean no memory leaks probably one of the most common causes of memory leaks in c# are event handlers
Sossenbinder
Sossenbinder2y ago
If you want to identify them, use a memory profiler like DotMemory or the VS builtin one
JakenVeina
JakenVeina2y ago
to elaborate, memory leaks in general in C# take the form of this.....
public class MyParentClass
{
public List<MyChildClass> Children { get; init; }
}

public class MyChildClass
{
public MyParentClass Parent { get; init; }
}

var parent = new MyParentClass()
{
Children = new()
};

var child = new MyChildClass()
{
Parent = parent
};
parent.Children.Add(child);
public class MyParentClass
{
public List<MyChildClass> Children { get; init; }
}

public class MyChildClass
{
public MyParentClass Parent { get; init; }
}

var parent = new MyParentClass()
{
Children = new()
};

var child = new MyChildClass()
{
Parent = parent
};
parent.Children.Add(child);
each of these two object instances contains a reference to the other the method itself also contains references to both, in the form of the parent and child variables thus, both instances are "live" if a garbage collection ran, it would see both of these instances as still accessible from the root of the program I.E. it'll start from the Main() method, and all static stuff, and walk from reference to reference to build a logical tree these two instances would end up appearing in that logical tree, so they are considered live, and the garbage collector will leave them alone any instances that DON'T appear in the tree get collected and the garbage collector is responsible for creating ALL objects, so it keeps its own list of all objects that exist it knows when something is still accessible, or not if I were to move on in the above method and do
child = null;
child = null;
the child variable no longer counts as a reference to that particular object instance but the instance is still "live" because it's referenced within the Children collection of parent and parent is still referenced by the parent variable if I next do
parent.Children.Clear();
parent.Children.Clear();
now, the instance of MyChildClass is "orphaned" it still contains a reference back to the MyParentClass instance, but it's no longer possible for the garbage collector to walk to it parent doesn't contain a reference anymore, and child we nulled out so, that instance of MyChildClass is now a candidate for garbage collection the GC makes NO guarantees about when or if that memory will ever BE collected but the next time the GC happens to trigger a collection, it'll likely get collected in short, there's no leak present here we decided we're done with the MyChildClass instance, and we're not doing anything weird to prevent it from getting collected let's adjust the example to introduce a memory leak and like Cyberrex said, the most common one is an event hander
public class MyParentClass
{
public List<MyChildClass> Children { get; init; }

public event Action MyEvent;
}

public class MyChildClass
{
public MyChildClass(MyParentClass parent)
{
Parent = parent;
parent.MyEvent += () => ++EventCount;
}

public MyParentClass Parent { get; }

public int EventCount { get; private set; }
}

var parent = new MyParentClass()
{
Children = new()
{
new MyChildClass(parent)
}
};
public class MyParentClass
{
public List<MyChildClass> Children { get; init; }

public event Action MyEvent;
}

public class MyChildClass
{
public MyChildClass(MyParentClass parent)
{
Parent = parent;
parent.MyEvent += () => ++EventCount;
}

public MyParentClass Parent { get; }

public int EventCount { get; private set; }
}

var parent = new MyParentClass()
{
Children = new()
{
new MyChildClass(parent)
}
};
this time, we don't have a child variable, to keep the MyChildClass instance alive, so if we remove it from parent.Children that makes it subject to collection, yeah?
parent.Children.Clear();
parent.Children.Clear();
well, no the event delegate in MyParentClass actually still has a reference to the MyChildClass instance in the form of the delegate that was created in the MyChildClass constructor, and attached to the event that anonymous method gets translated by the compiler into an instance method upon MyChildClass cause that's the only way the method can have access to instance fields on the class the EventCount property, in particular and in order for MyParentClass to call that method when the event occurs, it has to have a reference to it here, we have written code that, logically, says we don't want this child anymore, but mechanically, it's still being kept around if this parent instance is something that lasts a long time in your application, children regularly being added and removed, every removed child ends up getting "leaked" it takes up memory that you don't functionally "want" anymore, but which the garbage collector never knows it can collect so, in answer to the original question, always keep in mind what references you're creating and how you're maintaining them
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server