Click to See Complete Forum and Search --> : Memory leak example?


code?
November 5th, 2008, 03:20 AM
Is there any way I can do a tiny memory leak application, to see what it would do? Just wondering for experimental reasons.

wildfrog
November 5th, 2008, 03:31 AM
You could keep on adding elements to some kind of collection (List, Dictionary etc.).

- petter

TheCPUWizard
November 5th, 2008, 07:53 AM
You could keep on adding elements to some kind of collection (List, Dictionary etc.).

- petter

How would that generate a leak????

DeepT
November 5th, 2008, 11:23 AM
The classic memory leak in C# come from event handlers.

Take some core object that never goes away for the life of the application. Then take some other object which instanced for a while and then it is supposed to go away.

The Other object subscribes to an event on the core object. Now the core object has a reference to this other object in its event handler. You go along and empty your collection of objects thinking the GC will clean everything up. However, those objects never get cleaned up, because Core object's event has a reference to it.

The fix for this is simply to unsubscribe to the event, thus removing the reference.

TheCPUWizard
November 5th, 2008, 01:20 PM
The classic memory leak in C# come from event handlers.

Take some core object that never goes away for the life of the application. Then take some other object which instanced for a while and then it is supposed to go away.

The Other object subscribes to an event on the core object. Now the core object has a reference to this other object in its event handler. You go along and empty your collection of objects thinking the GC will clean everything up. However, those objects never get cleaned up, because Core object's event has a reference to it.

The fix for this is simply to unsubscribe to the event, thus removing the reference.

This is a VERY common problem. I find it in about 80% of .NET applications I am called in on.

Technically this is not a leak, as:

1) The object is still referencable (ie the event will continue to call it)
2) The object will be properly destroyed (albiet at program termination).

One common solution it to use the "Weak Event Model". However this does add some overhead on each invokation of the event.

A less common but [IMHO] better solution is the "Owned Delegate Model". In this model there is a bidirectional tie between the (wrapper for the) delegate and the recieving object.

MANUALLY unsubscribing works, but it is soo easy to miss

DeepT
November 5th, 2008, 02:12 PM
In a manged language it is a close to a memory leak as you can get. If you (not CPUWizard, but people in general) wanted to be super-anal about it, you would simply say memory leaks are impossible and strike the word from the C# lexicon.

Now you could go on about unmanaged code, but we are talking about managed code, C#, not COM interoperability or DLLs written in C++ that can leak.

DeepT
November 5th, 2008, 02:14 PM
A less common but [IMHO] better solution is the "Owned Delegate Model". In this model there is a bidirectional tie between the (wrapper for the) delegate and the recieving object.

An example of this would be great.

TheCPUWizard
November 5th, 2008, 02:52 PM
An example of this would be great.

A "working" example would be too big to post here (might be time for an article ;) ), but The concept is simple....

(This code is typed in RAW and for conceptual purposes only...)

public class OwnedDelegates : List<OwnedDelegate>
{
public static OwnedDelegates Global = new OwnedDelegates();
public void Register(OwnedDelegate item)
{
Add(item);
}

public void Unregister(OwnedDelegate item)
{
Remove(item);
}


public void ReleaseAll(object owner)
{
List<OwnedDelegate> killList = new List<OwnedDelegate>();
foreach (OwnedDelegate item in this)
{
if (item.IsOwnedBy(owner))
{
item.Invalidate();
killList.Add(item);
}
}
foreach (OwnedDelegate item in killList)
{
Remove(item);
}
}
}

public abstract class OwnedDelegate
{
public abstract void Invalidate();
public abstract bool IsOwnedBy(Object owner);
public abstract bool IsAlive { get; }
}

public class OwnedDelegate<EVENT_TYPE> : OwnedDelegate
where EVENT_TYPE : EventArgs
{
public static EventHandler<EVENT_TYPE> Create(EventHandler<EVENT_TYPE> handler)
{
OwnedDelegate<EVENT_TYPE> instance = new OwnedDelegate<EVENT_TYPE>(handler);
OwnedDelegates.Global.Register(instance);
return instance.Delegate;
}

public override bool IsOwnedBy(Object owner)
{

if (IsAlive)
return ReferenceEquals(m_Owner.Target, owner);
else
return false;
}

public override bool IsAlive
{
get { return (m_Owner != null) && (m_Owner.IsAlive); }
}

public override void Invalidate()
{
m_RealHandler = null;
m_Owner = null;
OwnedDelegates.Global.Unregister(this);
}

private OwnedDelegate(EventHandler<EVENT_TYPE> handler)
{
m_Owner = new WeakReference(handler.Target);
m_RealHandler = handler;
m_MyHandler += OwnedDelegate_Handler;
}

public EventHandler<EVENT_TYPE> Delegate
{
get { return m_MyHandler; }
}

void OwnedDelegate_Handler(object sender, EVENT_TYPE e)
{
if (m_RealHandler != null)
m_RealHandler(sender, e);
}

private WeakReference m_Owner;
private event EventHandler<EVENT_TYPE> m_MyHandler;
private EventHandler<EVENT_TYPE> m_RealHandler;
}

Mutant_Fruit
November 5th, 2008, 02:58 PM
Just keep calling:

System.Runtime.InteropServices.Marshal.AllocHGlobal(10000);

and don't free the returned pointer.

DeepT
November 5th, 2008, 03:02 PM
That will take a couple of read-throughs, or maybe find a book. Or you can create an article on it.

DeepT
November 5th, 2008, 03:04 PM
Just keep calling:

System.Runtime.InteropServices.Marshal.AllocHGlobal(10000);

and don't free the returned pointer.

That is cheating and doesn't count. Once you leave the managed side of things, you are "out of bounds".

I can come up with better one then that

public void Loop() { Loop();}

TheCPUWizard
November 5th, 2008, 03:09 PM
DeepT ---- Just found out you do not have PM's enabled....please contact me.

DO NOT REPLY directly on forum to this particular reply. It will be deleted once contact is made.

Mutant_Fruit
November 5th, 2008, 03:12 PM
A stack overflow isn't a memory leak :P

You can't create a memory leak in C# unless you are exploiting a bug in the framework or are using unmanaged code.

Pure safe C# cannot leak.

DeepT
November 6th, 2008, 09:44 AM
I will define a memory leak for C#:

A leak is when your program consumes more and more memory and you have no idea why.

TheCPUWizard
November 6th, 2008, 10:19 AM
I will define a memory leak for C#:

A leak is when your program consumes more and more memory and you have no idea why.

One can not simply make up definitions for a word...unless...

I hereby define "fun" as "Send large sums of money to the CPUWizard". I want EVERYBODY th have FUN!!!!!

A leak is characterized by two qualities.

1) The resource is not referencable
2) The resource will not be properly "cleaned up".

Unless these two conditions come into play, it is NOT a leak!!!!!!

Improper Object Lifetime Management is a completely different topic. "Excessive" memory usage is one symptom of this.

Two ironic points:

1) EXPLICITLY calling GC.Collect can actually induce increased memory usage. :sick:

2) .NET really does not have "garbage collection" for most objects (objects with 85,000 or more bytes of direct allocation are the exception). On the other hand native C++ almost ALWAYS has "garbage collection". :eek::D:eek::D:confused::confused:

DeepT
November 6th, 2008, 02:44 PM
May I refer you to this post. (http://www.codeguru.com/forum/showpost.php?p=1778521&postcount=6)

Also, I have my PMs enabled now, so what is it you wanted to say?

Addendum: Perhaps the mods can add the words "Memory Leak" to the bad words filter for the C# forum.

wildfrog
November 7th, 2008, 06:52 AM
How would that generate a leak????

Here is my and wikipedia definition on a memory leak:
In computer science, a memory leak is a particular type of unintentional memory consumption by a computer program where the program fails to release memory when no longer needed. This condition is normally the result of a bug in a program that prevents it from freeing up memory that it no longer needs.
If you unintentionally use up more and more memory... you got a leak.

- petter

MNovy
November 7th, 2008, 07:05 AM
Is the philosophy of .NET not to avoid mem leaks by using the Garbage Collector?

I thought that .NET takes care about used memory and releases it, if
required.

So for .NET developers no memory leaks can occur.

If I'm wrong, tell me.

TheCPUWizard
November 7th, 2008, 09:16 AM
Here is my and wikipedia definition on a memory leak:

In computer science, a memory leak is a particular type of unintentional memory consumption by a computer program where the program fails to release memory when no longer needed. This condition is normally the result of a bug in a program that prevents it from freeing up memory that it no longer needs..

- petter

1) NEVER trust WikiPedia...It is often a good starting point, but a many (most?) items contain at least one (typically minor) in-accuracy...

In the case of the "dangling event", it will does not meet the criteria as it does not satisify the "no longer needs" portion.


1) WE sign a contract that you will notify me of certain facts when something happens.

2) Time passes, and I no longer care about this, but do NOT inform you and have the contract terminated (along with any side effects of the termination)

3) YOU still have the responsibility of notifying me.

4) I still have the responsibility of accepting that notification.

If I terminate my means of accdepting the notification, I would be in violation of the contract. I must (legally) keep the means of communication open.

Now if we translate this into the "event" issue, we see the same exact condition. The object is question (the one with no references OTHER THAN the contractual reference in the delegate) is OBLIGATED to remain in existance. It is STILL REQUIRED.

To go to a more general case, consider that EVERY object "exists" for a period of time in .NET after it is no longer needed (from the removal of the last reference to the object, until the GC runs for the generation which owns the object. From a programmers perspective, the object is "no longer needed". But this is not considered a leak....