By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,656 Members | 968 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,656 IT Pros & Developers. It's quick & easy.

Memory Leak in managed Code

P: n/a
The following code will create memory leaks!!!
using System;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
namespace MemoryLeak
{
public class RGCSqlConnection:System.IDisposable
{
SqlConnection m_connSQL;
public RGCSqlConnection(string dbName, string serverName)
{
string ServerName=serverName;
string DBName=dbName;
string m_strConn="Connection Timeout=45;Integrated Security=SSPI;Persist
Security Info=False;Initial Catalog=" + dbName + ";Data Source=" +
serverName;
m_connSQL= new SqlConnection(m_strConn);
m_connSQL.Open();
}
#region IDisposable Members

public void Dispose()
{
m_connSQL.Dispose();
}

#endregion
}

public class TestClass
{
int [] a=new int [100];
~TestClass()
{
}
[STAThread]
static void Main()
{
RGCSqlConnection conn = new RGCSqlConnection("Northwind","localhost");
conn.Dispose();

TestClass t;
do
{
t=new TestClass();
}
while (true);
}
}

}

Dec 23 '05 #1
Share this Question
Share on Google+
23 Replies


P: n/a
James wrote:
The following code will create memory leaks!!!
using System;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
namespace MemoryLeak
{
public class RGCSqlConnection:System.IDisposable
{
SqlConnection m_connSQL;
public RGCSqlConnection(string dbName, string serverName)
{
string ServerName=serverName;
string DBName=dbName;
string m_strConn="Connection Timeout=45;Integrated Security=SSPI;Persist
Security Info=False;Initial Catalog=" + dbName + ";Data Source=" +
serverName;
m_connSQL= new SqlConnection(m_strConn);
m_connSQL.Open();
}
#region IDisposable Members

public void Dispose()
{
m_connSQL.Dispose();
}

#endregion
}

public class TestClass
{
int [] a=new int [100];
~TestClass()
{
}
[STAThread]
static void Main()
{
RGCSqlConnection conn = new RGCSqlConnection("Northwind","localhost");
conn.Dispose();

TestClass t;
do
{
t=new TestClass();
}
while (true);
}
}

}


I don't think that you have an understanding of what a memory leak is.
Calling dispose will just mark the object from Garbage Collection, the
objects will eventially get disposed of, but not right away. To test
for a memory leak, run your app, then close it and see if resources are
returned to the heap.

--
Rob Schieber
Dec 23 '05 #2

P: n/a
I understand what you said.
Please run the code and see if the memory goes up. The memory leak problem
that I talked about happens in the while loop

-James

"Rob Schieber" wrote:
James wrote:
The following code will create memory leaks!!!
using System;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
namespace MemoryLeak
{
public class RGCSqlConnection:System.IDisposable
{
SqlConnection m_connSQL;
public RGCSqlConnection(string dbName, string serverName)
{
string ServerName=serverName;
string DBName=dbName;
string m_strConn="Connection Timeout=45;Integrated Security=SSPI;Persist
Security Info=False;Initial Catalog=" + dbName + ";Data Source=" +
serverName;
m_connSQL= new SqlConnection(m_strConn);
m_connSQL.Open();
}
#region IDisposable Members

public void Dispose()
{
m_connSQL.Dispose();
}

#endregion
}

public class TestClass
{
int [] a=new int [100];
~TestClass()
{
}
[STAThread]
static void Main()
{
RGCSqlConnection conn = new RGCSqlConnection("Northwind","localhost");
conn.Dispose();

TestClass t;
do
{
t=new TestClass();
}
while (true);
}
}

}


I don't think that you have an understanding of what a memory leak is.
Calling dispose will just mark the object from Garbage Collection, the
objects will eventially get disposed of, but not right away. To test
for a memory leak, run your app, then close it and see if resources are
returned to the heap.

--
Rob Schieber

Dec 23 '05 #3

P: n/a

"James" <Ja***@discussions.microsoft.com> wrote in message
news:58**********************************@microsof t.com...
The following code will create memory leaks!!!
using System;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
namespace MemoryLeak
{
public class RGCSqlConnection:System.IDisposable
{
SqlConnection m_connSQL;
public RGCSqlConnection(string dbName, string serverName)
{
string ServerName=serverName;
string DBName=dbName;
string m_strConn="Connection Timeout=45;Integrated Security=SSPI;Persist
Security Info=False;Initial Catalog=" + dbName + ";Data Source=" +
serverName;
m_connSQL= new SqlConnection(m_strConn);
m_connSQL.Open();
}
#region IDisposable Members

public void Dispose()
{
m_connSQL.Dispose();
}

#endregion
}

public class TestClass
{
int [] a=new int [100];
~TestClass()
{
}
[STAThread]
static void Main()
{
RGCSqlConnection conn = new RGCSqlConnection("Northwind","localhost");
conn.Dispose();

TestClass t;
do
{
t=new TestClass();
}
while (true);
}
}

}


No it won't, what makes you think that?
Note that you should not implement IDisposable and your TestClass should not
have a destructor (Finalize).

Willy.
Dec 23 '05 #4

P: n/a
That's something that I dont understand.

Why does the destructor make difference?

Change the t to be a Form class, it will cause the memory leak too.

I tried to add (Application.Doevent()) which might eventually fixed the
memory leak problem here, but in my case (which is a much larger windows form
class) will still have the memory leak problem. I really dont understand why.
All my code is managed code and only use .NET libary ( No third party libs).
It is supposed not to have memory leaks, isn't it?

-James
"Willy Denoyette [MVP]" wrote:

"James" <Ja***@discussions.microsoft.com> wrote in message
news:58**********************************@microsof t.com...
The following code will create memory leaks!!!
using System;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
namespace MemoryLeak
{
public class RGCSqlConnection:System.IDisposable
{
SqlConnection m_connSQL;
public RGCSqlConnection(string dbName, string serverName)
{
string ServerName=serverName;
string DBName=dbName;
string m_strConn="Connection Timeout=45;Integrated Security=SSPI;Persist
Security Info=False;Initial Catalog=" + dbName + ";Data Source=" +
serverName;
m_connSQL= new SqlConnection(m_strConn);
m_connSQL.Open();
}
#region IDisposable Members

public void Dispose()
{
m_connSQL.Dispose();
}

#endregion
}

public class TestClass
{
int [] a=new int [100];
~TestClass()
{
}
[STAThread]
static void Main()
{
RGCSqlConnection conn = new RGCSqlConnection("Northwind","localhost");
conn.Dispose();

TestClass t;
do
{
t=new TestClass();
}
while (true);
}
}

}


No it won't, what makes you think that?
Note that you should not implement IDisposable and your TestClass should not
have a destructor (Finalize).

Willy.

Dec 23 '05 #5

P: n/a
James,

Memory leaks are possible in .NET and there are examples in the framework.
Memory leaks are usually associated with managed class using unmanaged
resources. However it is not that easy to spot a memory leak in .NET.

You say in the while loop memory consumptions grow. This is normal. It will
grow until the CLR decides to GC the heap. When it will happen well it
depends. It definitiely won't happen with a simple application and alot of
free memory at application's disposal.

When the GC kicks off again the memory consuption may not go down
completely. Objects that have finalizers it takes 2 GC cycles to be
collected it also depends on object generation, etc. Thre are more to that.
SqlConnections are kept in a pool so even if you close a connection the
object stays pooled.

It is not that easy to localize a memory leak. More often memory leaks
happen because programmers keep some hidden and forgotten references to
unused objects than memory leaks due to bugs in the frameworks.
--

Stoitcho Goutsev (100) [C# MVP]

"James" <Ja***@discussions.microsoft.com> wrote in message
news:85**********************************@microsof t.com...
I understand what you said.
Please run the code and see if the memory goes up. The memory leak problem
that I talked about happens in the while loop

-James

"Rob Schieber" wrote:
James wrote:
> The following code will create memory leaks!!!
>
>
> using System;
> using System.Diagnostics;
> using System.Data;
> using System.Data.SqlClient;
>
>
> namespace MemoryLeak
> {
> public class RGCSqlConnection:System.IDisposable
> {
> SqlConnection m_connSQL;
> public RGCSqlConnection(string dbName, string serverName)
> {
> string ServerName=serverName;
> string DBName=dbName;
> string m_strConn="Connection Timeout=45;Integrated
> Security=SSPI;Persist
> Security Info=False;Initial Catalog=" + dbName + ";Data Source=" +
> serverName;
> m_connSQL= new SqlConnection(m_strConn);
> m_connSQL.Open();
> }
> #region IDisposable Members
>
> public void Dispose()
> {
> m_connSQL.Dispose();
> }
>
> #endregion
> }
>
> public class TestClass
> {
> int [] a=new int [100];
> ~TestClass()
> {
> }
>
>
> [STAThread]
> static void Main()
> {
> RGCSqlConnection conn = new RGCSqlConnection("Northwind","localhost");
> conn.Dispose();
>
> TestClass t;
> do
> {
> t=new TestClass();
> }
> while (true);
> }
> }
>
> }
>


I don't think that you have an understanding of what a memory leak is.
Calling dispose will just mark the object from Garbage Collection, the
objects will eventially get disposed of, but not right away. To test
for a memory leak, run your app, then close it and see if resources are
returned to the heap.

--
Rob Schieber

Dec 23 '05 #6

P: n/a

"James" <Ja***@discussions.microsoft.com> wrote in message
news:58**********************************@microsof t.com...
The following code will create memory leaks!!!


What you understand to be a memory leak is in fact not a memory leak. The
..Net framework gives excess memory allocation to the requesting application
if the system can spare it. Because it is so expensive to allocate more and
more memory, the system is generous when an application asks the system for
some more memory. If the application requests a little bit more (say 1 MB),
the system may give 5 or 10 MB, just so the application doesn't have to
request memory so much.

When the system starts to get low on resources, the application will return
memory back to the system. Here is a test to see a work-around for your
problem. After the loop finishes, look at how much memory your application
is using then minimize the application. Does the memory change? :)

Mythran

Dec 23 '05 #7

P: n/a
Thanks for replying.
I understand the GC will collect the garbic at a certain time indefintely.
However, if you ran the code, you will see the memory is never going down,
which I assume is a memory leak. In my real application, it is a much more
complex windows form, but the main function is exactly what i wrote in the
post.

-James
"Stoitcho Goutsev (100) [C# MVP]" wrote:
James,

Memory leaks are possible in .NET and there are examples in the framework.
Memory leaks are usually associated with managed class using unmanaged
resources. However it is not that easy to spot a memory leak in .NET.

You say in the while loop memory consumptions grow. This is normal. It will
grow until the CLR decides to GC the heap. When it will happen well it
depends. It definitiely won't happen with a simple application and alot of
free memory at application's disposal.

When the GC kicks off again the memory consuption may not go down
completely. Objects that have finalizers it takes 2 GC cycles to be
collected it also depends on object generation, etc. Thre are more to that.
SqlConnections are kept in a pool so even if you close a connection the
object stays pooled.

It is not that easy to localize a memory leak. More often memory leaks
happen because programmers keep some hidden and forgotten references to
unused objects than memory leaks due to bugs in the frameworks.
--

Stoitcho Goutsev (100) [C# MVP]

"James" <Ja***@discussions.microsoft.com> wrote in message
news:85**********************************@microsof t.com...
I understand what you said.
Please run the code and see if the memory goes up. The memory leak problem
that I talked about happens in the while loop

-James

"Rob Schieber" wrote:
James wrote:
> The following code will create memory leaks!!!
>
>
> using System;
> using System.Diagnostics;
> using System.Data;
> using System.Data.SqlClient;
>
>
> namespace MemoryLeak
> {
> public class RGCSqlConnection:System.IDisposable
> {
> SqlConnection m_connSQL;
> public RGCSqlConnection(string dbName, string serverName)
> {
> string ServerName=serverName;
> string DBName=dbName;
> string m_strConn="Connection Timeout=45;Integrated
> Security=SSPI;Persist
> Security Info=False;Initial Catalog=" + dbName + ";Data Source=" +
> serverName;
> m_connSQL= new SqlConnection(m_strConn);
> m_connSQL.Open();
> }
> #region IDisposable Members
>
> public void Dispose()
> {
> m_connSQL.Dispose();
> }
>
> #endregion
> }
>
> public class TestClass
> {
> int [] a=new int [100];
> ~TestClass()
> {
> }
>
>
> [STAThread]
> static void Main()
> {
> RGCSqlConnection conn = new RGCSqlConnection("Northwind","localhost");
> conn.Dispose();
>
> TestClass t;
> do
> {
> t=new TestClass();
> }
> while (true);
> }
> }
>
> }
>

I don't think that you have an understanding of what a memory leak is.
Calling dispose will just mark the object from Garbage Collection, the
objects will eventially get disposed of, but not right away. To test
for a memory leak, run your app, then close it and see if resources are
returned to the heap.

--
Rob Schieber


Dec 23 '05 #8

P: n/a
That's what I was trying to explain the fact that memory grows doesn
ncessary means there is a memory leak.

Your test I see has nothing to do with the Connection class you've created.
Your test is basically a class that upon creation allocates array of 100
intgers.

And in a loop you create isntances of this class - 100 integers every time.
You say that there is a memory leak because everytime you create a new
object of this TestClass the memory consumption grows. Is that correct?

What do you expect to happen? What is the correct behavior? On every loop
you get more memory, why shouldn't memory grow?

BTW, you made it even harder for the GC declaring this empty destructor
(finalizer).
--

Stoitcho Goutsev (100) [C# MVP]

"James" <Ja***@discussions.microsoft.com> wrote in message
news:04**********************************@microsof t.com...
Thanks for replying.
I understand the GC will collect the garbic at a certain time indefintely.
However, if you ran the code, you will see the memory is never going down,
which I assume is a memory leak. In my real application, it is a much more
complex windows form, but the main function is exactly what i wrote in the
post.

-James
"Stoitcho Goutsev (100) [C# MVP]" wrote:
James,

Memory leaks are possible in .NET and there are examples in the
framework.
Memory leaks are usually associated with managed class using unmanaged
resources. However it is not that easy to spot a memory leak in .NET.

You say in the while loop memory consumptions grow. This is normal. It
will
grow until the CLR decides to GC the heap. When it will happen well it
depends. It definitiely won't happen with a simple application and alot
of
free memory at application's disposal.

When the GC kicks off again the memory consuption may not go down
completely. Objects that have finalizers it takes 2 GC cycles to be
collected it also depends on object generation, etc. Thre are more to
that.
SqlConnections are kept in a pool so even if you close a connection the
object stays pooled.

It is not that easy to localize a memory leak. More often memory leaks
happen because programmers keep some hidden and forgotten references to
unused objects than memory leaks due to bugs in the frameworks.
--

Stoitcho Goutsev (100) [C# MVP]

"James" <Ja***@discussions.microsoft.com> wrote in message
news:85**********************************@microsof t.com...
>I understand what you said.
> Please run the code and see if the memory goes up. The memory leak
> problem
> that I talked about happens in the while loop
>
> -James
>
> "Rob Schieber" wrote:
>
>> James wrote:
>> > The following code will create memory leaks!!!
>> >
>> >
>> > using System;
>> > using System.Diagnostics;
>> > using System.Data;
>> > using System.Data.SqlClient;
>> >
>> >
>> > namespace MemoryLeak
>> > {
>> > public class RGCSqlConnection:System.IDisposable
>> > {
>> > SqlConnection m_connSQL;
>> > public RGCSqlConnection(string dbName, string serverName)
>> > {
>> > string ServerName=serverName;
>> > string DBName=dbName;
>> > string m_strConn="Connection Timeout=45;Integrated
>> > Security=SSPI;Persist
>> > Security Info=False;Initial Catalog=" + dbName + ";Data Source=" +
>> > serverName;
>> > m_connSQL= new SqlConnection(m_strConn);
>> > m_connSQL.Open();
>> > }
>> > #region IDisposable Members
>> >
>> > public void Dispose()
>> > {
>> > m_connSQL.Dispose();
>> > }
>> >
>> > #endregion
>> > }
>> >
>> > public class TestClass
>> > {
>> > int [] a=new int [100];
>> > ~TestClass()
>> > {
>> > }
>> >
>> >
>> > [STAThread]
>> > static void Main()
>> > {
>> > RGCSqlConnection conn = new
>> > RGCSqlConnection("Northwind","localhost");
>> > conn.Dispose();
>> >
>> > TestClass t;
>> > do
>> > {
>> > t=new TestClass();
>> > }
>> > while (true);
>> > }
>> > }
>> >
>> > }
>> >
>>
>> I don't think that you have an understanding of what a memory leak is.
>> Calling dispose will just mark the object from Garbage Collection, the
>> objects will eventially get disposed of, but not right away. To test
>> for a memory leak, run your app, then close it and see if resources
>> are
>> returned to the heap.
>>
>> --
>> Rob Schieber
>>


Dec 23 '05 #9

P: n/a

"James" <Ja***@discussions.microsoft.com> wrote in message
news:4C**********************************@microsof t.com...
That's something that I dont understand.

Why does the destructor make difference?

It has nothing to do with your so called memory leak. However, It's not
needed, worse it creates some overhead as each object must be registered as
a finalizable object, so it needs two GC runs before getting collected.

Change the t to be a Form class, it will cause the memory leak too.

I tried to add (Application.Doevent()) which might eventually fixed the
memory leak problem here, but in my case (which is a much larger windows
form
class) will still have the memory leak problem. I really dont understand
why.
All my code is managed code and only use .NET libary ( No third party
libs).
It is supposed not to have memory leaks, isn't it?

-James


When I run the code you posted (both on v1.1 4322 SP1 and v2 of the
framework), the "working set" stays the same ~12MB and the private bytes
stay at ~9MB. That means there is no leak at all.
I realy don't know what values you are measuring and what version of the
framework you are running, so it would help us if you post your memory
counter values.
Willy.
Dec 23 '05 #10

P: n/a
James <Ja***@discussions.microsoft.com> wrote:
That's something that I dont understand.

Why does the destructor make difference?
Because that means the finalizer needs to be run before the instance
can be garbage collected.
Change the t to be a Form class, it will cause the memory leak too.

I tried to add (Application.Doevent()) which might eventually fixed the
memory leak problem here, but in my case (which is a much larger windows form
class) will still have the memory leak problem. I really dont understand why.
All my code is managed code and only use .NET libary ( No third party libs).
It is supposed not to have memory leaks, isn't it?


I strongly suspect you're running into an interesting problem with
STAThreads. I have a sneaking suspicion that finalizers for objects
created on STA threads are actually executed within that thread -
otherwise you'd have difficulty with things which should only ever be
accessed on that thread.

Now, normally that's not a problem, because you'd normally create a UI
thread and let it do its message pumping appropriately. In your case,
you're blocking the thread, so it can't run the finalizer.

This is all only a suspicion, but given what you say about
Application.DoEvents (which would allow the UI to run the message pump
and thus the finalizers) it sounds likely.

Basically, you shouldn't block your thread - or you shouldn't be using
STAThread in the first place. Frankly I've always thought it a shame
that the COM apartments have inveigled their way into .NET, but I guess
that's the price you pay for pretty good COM interop.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 23 '05 #11

P: n/a
Willy Denoyette [MVP] <wi*************@telenet.be> wrote:
"James" <Ja***@discussions.microsoft.com> wrote in message
news:4C**********************************@microsof t.com...
That's something that I dont understand.

Why does the destructor make difference?
It has nothing to do with your so called memory leak. However, It's not
needed, worse it creates some overhead as each object must be registered as
a finalizable object, so it needs two GC runs before getting collected.


Actually, it has everything to do with the memory leak, if I understand
what's going on. I believe that at least one finalizer (probably
something to do with SQL Server) is blocked, trying to get back onto
the main thread (which is busy) and so none of the other finalizers (of
TestClass) are executing - and thus the instances aren't getting
collected.

<snip>
When I run the code you posted (both on v1.1 4322 SP1 and v2 of the
framework), the "working set" stays the same ~12MB and the private bytes
stay at ~9MB. That means there is no leak at all.


Interestingly, I see no leak with 2.0, but I *do* see a leak with 1.1.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 23 '05 #12

P: n/a
Mythran <ki********@hotmail.comREMOVETRAIL> wrote:
"James" <Ja***@discussions.microsoft.com> wrote in message
news:58**********************************@microsof t.com...
The following code will create memory leaks!!!


What you understand to be a memory leak is in fact not a memory leak.


It sort of is, actually. The finalizer thread is getting blocked, so
none of the test class instances are getting collected. I believe the
finalizer thread is waiting to execute code on the STAThread, which it
can't do because that thread is always busy.

It's worth noting that any of the following remove the problem:

1) Running under .NET 2.0
2) Removing the creation/disposal of the connection
3) Removing the STAThread attribute
4) Removing the finalizer from TestClass

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 23 '05 #13

P: n/a
Hi,



When I run the code you posted (both on v1.1 4322 SP1 and v2 of the
framework), the "working set" stays the same ~12MB and the private bytes
stay at ~9MB. That means there is no leak at all.
I realy don't know what values you are measuring and what version of the
framework you are running, so it would help us if you post your memory
counter values.

I do see the same thing than James, in my machine V1.1 XP sp2 1GB ram the
memory use increase until all memory is used. It does return to normality
when the program is stopped.

The wierd thing is that the destructor is never called

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation
Dec 23 '05 #15

P: n/a
Jon Skeet [C# MVP] <sk***@pobox.com> wrote:
I strongly suspect you're running into an interesting problem with
STAThreads. I have a sneaking suspicion that finalizers for objects
created on STA threads are actually executed within that thread -
otherwise you'd have difficulty with things which should only ever be
accessed on that thread.

Now, normally that's not a problem, because you'd normally create a UI
thread and let it do its message pumping appropriately. In your case,
you're blocking the thread, so it can't run the finalizer.


<snip>

I've finally found the blog post I was looking for which describes
this:

http://blogs.msdn.com/cbrumme/archiv.../02/66219.aspx

It's long and complicated, but this quote is significant:

<quote>
Assume for a moment that a Console application also puts its main
thread into an STA. If that main thread creates any COM objects via
COM Interop, and if those COM objects are ThreadingModel=Main or Both,
then the application better be pumping. If it fails to pump, we=3Fll
have exactly the same situation with our server running ASP
compatibility mode. The Finalizer thread won=3Ft be able to marshal
calls into the STA to Release any pUnks.
</quote>

I strongly suspect that the SQL client code is creating COM objects
with the above threading models, hence the problem.

Quite how it's been fixed in 2.0, I don't know...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 23 '05 #16

P: n/a
This is the difference between Reserved and Commited
memory.
This is a Windows feature, which has been around before .NET.
Roger

http://msdn.microsoft.com/library/de...ing_memory.asp

What you understand to be a memory leak is in fact not a memory leak. The
.Net framework gives excess memory allocation to the requesting application if the system can spare it. Because it is so expensive to allocate more and more memory, the system is generous when an application asks the system for some more memory. If the application requests a little bit more (say 1 MB), the system may give 5 or 10 MB, just so the application doesn't have to
request memory so much.

When the system starts to get low on resources, the application will return memory back to the system. Here is a test to see a work-around for your
problem. After the loop finishes, look at how much memory your application is using then minimize the application. Does the memory change? :)

Mythran

Dec 23 '05 #17

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Willy Denoyette [MVP] <wi*************@telenet.be> wrote:
"James" <Ja***@discussions.microsoft.com> wrote in message
news:4C**********************************@microsof t.com...
> That's something that I dont understand.
>
> Why does the destructor make difference?


It has nothing to do with your so called memory leak. However, It's not
needed, worse it creates some overhead as each object must be registered
as
a finalizable object, so it needs two GC runs before getting collected.


Actually, it has everything to do with the memory leak, if I understand
what's going on. I believe that at least one finalizer (probably
something to do with SQL Server) is blocked, trying to get back onto
the main thread (which is busy) and so none of the other finalizers (of
TestClass) are executing - and thus the instances aren't getting
collected.

<snip>
When I run the code you posted (both on v1.1 4322 SP1 and v2 of the
framework), the "working set" stays the same ~12MB and the private bytes
stay at ~9MB. That means there is no leak at all.


Interestingly, I see no leak with 2.0, but I *do* see a leak with 1.1.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too


I'm running this on v1.1 and v2.0 without any leak at all.
But I do have a connection with an SQL server on another Server using TCP.
I guess that the OP's issue relates to the local connection using shared
memory IPC mechanism.
That would mean that the Finalizer thread is blocked and as such isn't able
to run the finalize methods of the TestClass instances, effectively
preventing the GC to collect the instances.
I can't try this with a local instance of SQL in order to see if this
relates to v1.1, but I trust your findings and think this is a bug in v1.1
SqlClient namespace, probaly only using shared memory as IPC channel. Maybe
one of you could verify this and try with named pipe and TCP channels.

Willy.


Dec 23 '05 #18

P: n/a

"Ignacio Machin ( .NET/ C# MVP )" <ignacio.machin AT dot.state.fl.us> wrote
in message news:eE***************@TK2MSFTNGP15.phx.gbl...
Hi,



When I run the code you posted (both on v1.1 4322 SP1 and v2 of the
framework), the "working set" stays the same ~12MB and the private bytes
stay at ~9MB. That means there is no leak at all.
I realy don't know what values you are measuring and what version of the
framework you are running, so it would help us if you post your memory
counter values.

I do see the same thing than James, in my machine V1.1 XP sp2 1GB ram the
memory use increase until all memory is used. It does return to normality
when the program is stopped.

The wierd thing is that the destructor is never called

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation


See my reply to Jon's post.

Willy.
Dec 23 '05 #19

P: n/a
Hi Willy,


I'm running this on v1.1 and v2.0 without any leak at all.
But I do have a connection with an SQL server on another Server using TCP.
I guess that the OP's issue relates to the local connection using shared
memory IPC mechanism.
That would mean that the Finalizer thread is blocked and as such isn't
able to run the finalize methods of the TestClass instances, effectively
preventing the GC to collect the instances.
I can't try this with a local instance of SQL in order to see if this
relates to v1.1, but I trust your findings and think this is a bug in v1.1
SqlClient namespace, probaly only using shared memory as IPC channel.
Maybe one of you could verify this and try with named pipe and TCP
channels.

Willy.

I tested this with a remote server and the same thing happened.
--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation
Dec 23 '05 #20

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP***********************@msnews.microsoft.co m...
Mythran <ki********@hotmail.comREMOVETRAIL> wrote:
"James" <Ja***@discussions.microsoft.com> wrote in message
news:58**********************************@microsof t.com...
> The following code will create memory leaks!!!


What you understand to be a memory leak is in fact not a memory leak.


It sort of is, actually. The finalizer thread is getting blocked, so
none of the test class instances are getting collected. I believe the
finalizer thread is waiting to execute code on the STAThread, which it
can't do because that thread is always busy.

It's worth noting that any of the following remove the problem:

1) Running under .NET 2.0
2) Removing the creation/disposal of the connection
3) Removing the STAThread attribute
4) Removing the finalizer from TestClass

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too


Jon,

Could add a call To WaitForPendingFinalizers() after the Dispose call, with
the STAThread set and see what happens?
I'm looking at the v1.1 sources and found a COM dependency, this part is
somewhat complex code so before I go deeper I would see this confirmed.
Why? Well, it would confirm that the finalizer is blocked trying to finalize
the RCW on an STA thread that doesn't pump messages! (which is real bad).
That would also explain why there is no issue on an MTA thread.

Willy.
Dec 23 '05 #21

P: n/a

"Ignacio Machin ( .NET/ C# MVP )" <ignacio.machin AT dot.state.fl.us> wrote
in message news:OK**************@TK2MSFTNGP12.phx.gbl...
Hi Willy,


I'm running this on v1.1 and v2.0 without any leak at all.
But I do have a connection with an SQL server on another Server using
TCP.
I guess that the OP's issue relates to the local connection using shared
memory IPC mechanism.
That would mean that the Finalizer thread is blocked and as such isn't
able to run the finalize methods of the TestClass instances, effectively
preventing the GC to collect the instances.
I can't try this with a local instance of SQL in order to see if this
relates to v1.1, but I trust your findings and think this is a bug in
v1.1 SqlClient namespace, probaly only using shared memory as IPC
channel. Maybe one of you could verify this and try with named pipe and
TCP channels.

Willy.

I tested this with a remote server and the same thing happened.


Ignacio,

You mean it's leaking, right? Weird, I run this on v1.1.4322 SP1 XP SP2 with
SQL2005 as backend on W2K3.
I'm also using SSPI as security protocol. I will double check to see if I'm
not mixing v1.1 and v2 stuff.

Willy.
Dec 23 '05 #22

P: n/a

"Ignacio Machin ( .NET/ C# MVP )" <ignacio.machin AT dot.state.fl.us> wrote
in message news:OK**************@TK2MSFTNGP12.phx.gbl...
Hi Willy,


I'm running this on v1.1 and v2.0 without any leak at all.
But I do have a connection with an SQL server on another Server using
TCP.
I guess that the OP's issue relates to the local connection using shared
memory IPC mechanism.
That would mean that the Finalizer thread is blocked and as such isn't
able to run the finalize methods of the TestClass instances, effectively
preventing the GC to collect the instances.
I can't try this with a local instance of SQL in order to see if this
relates to v1.1, but I trust your findings and think this is a bug in
v1.1 SqlClient namespace, probaly only using shared memory as IPC
channel. Maybe one of you could verify this and try with named pipe and
TCP channels.

Willy.

I tested this with a remote server and the same thing happened.
--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation


Ok, guys I'm also experiencing the leak on 1.1.4233, must have made a
mistake when compiling. Sorry about the confusions.

Willy.
Dec 23 '05 #23

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP***********************@msnews.microsoft.co m...
Mythran <ki********@hotmail.comREMOVETRAIL> wrote:
"James" <Ja***@discussions.microsoft.com> wrote in message
news:58**********************************@microsof t.com...
> The following code will create memory leaks!!!


What you understand to be a memory leak is in fact not a memory leak.


It sort of is, actually. The finalizer thread is getting blocked, so
none of the test class instances are getting collected. I believe the
finalizer thread is waiting to execute code on the STAThread, which it
can't do because that thread is always busy.

It's worth noting that any of the following remove the problem:

1) Running under .NET 2.0
2) Removing the creation/disposal of the connection
3) Removing the STAThread attribute
4) Removing the finalizer from TestClass

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too


Ok, no need to check any further.
The 'leak' is due to a blocked finalizer thread because of a COM dependency
is the SqlClient namespace.
What you should do is call GC.WaitForPendingFinalizers() in order to pump
the message queue in an STA thread. Console applications don't pump messages
(actually they have no message queue), that's why I insist you should never
apply STAThread in a console (or console like) application.
This is an issue I posted several times about before, and the rule is
simple, if you really needs an STA thread for a console application you
should must pump messages.
To help you with this the framework provides API's like
WaitForPendingFinalizers(), WaitOne() and a couple of others that do pump
the queue (for COM messages only).
But again, if you don't need an STA thread, stay away from it, they are only
meant for Windows Forms applications UI threads.
Willy.

Dec 23 '05 #24

This discussion thread is closed

Replies have been disabled for this discussion.