472,804 Members | 1,249 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,804 software developers and data experts.

hunting down a memory leak

my w3wp.exe process has recently gotten an ever-expanding memory
footprint. the two most likely causes are either a memory leak in the
object library it uses, or session variables not getting cleaned up
correctly. this post is to check one thing in the object library, to
make sure that the "using" statement is being used correctly.

yes, i know that the use of error messaging is inadvisable and
unnecessary in .NET languages. we do plan to migrate this to use
exceptions in the future, however right now 90% of the consumers of
this object library are non.NET applications which cannot handle the
..NET exception classes.

public override bool LoadByID(string sID, string sConnection)
{
p_nErrorCode = 0;
p_sErrorMessage = "";

if (AuthorityID = Guid.Empty) return false;

bool bReturn = true;

using (SqlConnection oConn = new SqlConnection(sConnection))
using (SqlCommand oCommand =
this.CreateSqlCommand("parameterlist.xml", oConn))
{
try { oConn.Open(); }
catch (Exception ex)
{
p_nErrorCode = 10;
p_sErrorMessage = "Error opening DB conenction during .DBLoadByID:
" + ex.Message;
goto Failed;
}
oCommand.Parameters["@objectid"].Value = new Guid(sID);
oCommand.Parameters["@authorityid"].Value = p_gAuthorityID;

try { oCommand.ExecuteNonQuery(); }
catch (Exception ex)
{
p_nErrorCode = 10;
p_sErrorMessage = "Sql exception during LoadByID: " + ex.Message;
goto Failed;
}
if (Convert.IsDBNull(oCommand.Parameters["@rowcount"].Value))
{
p_nErrorCode = 10;
p_sErrorMessage = "Null rowcount during LoadByID.";
goto Failed;
}

int nEffect =
Convert.ToInt32(oCommand.Parameters["@rowcount"].Value);
if (nEffect == 1)
{
p_gID = new Guid(sID);
p_dtDateCreated =
GetDateTimeParameter(oCommand.Parameters["@datecreated"]);
p_dtDateModified =
GetDateTimeParameter(oCommand.Parameters["@datemodified"]);
p_gModifiedBy = (Guid)oCommand.Parameters["@modifiedby"].Value;

p_bLoaded = true;
}
else
{
p_nErrorCode = 10;
p_sErrorMessage = "Unexpected rowcount (" + nEffect + ") during
LoadByID.";
goto Failed;
}
Failed:
if (ErrorCode > 0) bReturn = false;
}
return bReturn;
}
and here is the stuff behind the function call above
"CreateSqlCommand":

public SqlCommand CreateSqlCommand(string sFileName, SqlConnection
oConn)
{
XMLCommand oXMLCommand = new XMLCommand();
SqlCommand oCommand = oXMLCommand.CreateSqlCommand(sFileName);
if (oCommand == null)
{
p_nErrorCode = oXMLCommand.ErrorCode;
p_sErrorMessage = oXMLCommand.ErrorMessage;
return null;
}
oCommand.Connection = oConn;
return oCommand;
}

and here is the stuff behind the XMLCommand.CreateSqlCommand method:

public SqlCommand CreateSqlCommand(string sFileName)
{
p_nErrorCode = 0;
p_sErrorMessage = "";

SerializedParameters oSP = null;
XmlSerializer oSerializer = new
XmlSerializer(typeof(SerializedParameters));

oSerializer.UnknownNode += new XmlNodeEventHandler(this.UnknownNode);
oSerializer.UnknownAttribute += new
XmlAttributeEventHandler(this.UnknownAttribute);

try
{
using (FileStream oFS = new FileStream(p_sXmlPath + sFileName,
FileMode.Open, FileAccess.Read, FileShare.Read))
{
oSP = (SerializedParameters) oSerializer.Deserialize(oFS);
oFS.Close();
}
}
catch(Exception ex)
{
p_nErrorCode = 10;
p_sErrorMessage = "Error accessing or serializing XML document: " +
ex.Message;
goto Failed;
}
oSerializer = null;
Failed:
if (ErrorCode > 0) return null;
return oSP.CreateSqlCommand();
}

so is there anything in here that looks like it would likely cause a
memory leak? many thanks for the scrutiny and suggestions.

jason

Nov 30 '05 #1
4 2507
Couple things that stood right out for me (others may have more comments):

First, it appears that the using statement near the top for your SqlConnection
doesn't have anything "inside it". The whole idea of this statement is to
automatically call Dispose on the object after the closing brace. So for
example:

using (SqlConnection oConn = new SqlConnection(sConnection))
{
// your business logic here
}

The other pattern I see is that you have a bunch of try statments with no
closing Finally statement in which one would normally close a connection.
Basicaly if you are going to do
oCommand.ExecuteNonQuery();

you want to have a finally block that will close the connection on an
exception since there isn't likely anything further down the line that you
could ever do.

I'd refactor the whole thing, and get rid of the "GOTO's".

Good Luck,
peter
--
Co-founder, Eggheadcafe.com developer portal:
http://www.eggheadcafe.com
UnBlog:
http://petesbloggerama.blogspot.com


"jason" wrote:
my w3wp.exe process has recently gotten an ever-expanding memory
footprint. the two most likely causes are either a memory leak in the
object library it uses, or session variables not getting cleaned up
correctly. this post is to check one thing in the object library, to
make sure that the "using" statement is being used correctly.

yes, i know that the use of error messaging is inadvisable and
unnecessary in .NET languages. we do plan to migrate this to use
exceptions in the future, however right now 90% of the consumers of
this object library are non.NET applications which cannot handle the
..NET exception classes.

public override bool LoadByID(string sID, string sConnection)
{
p_nErrorCode = 0;
p_sErrorMessage = "";

if (AuthorityID = Guid.Empty) return false;

bool bReturn = true;

using (SqlConnection oConn = new SqlConnection(sConnection))
using (SqlCommand oCommand =
this.CreateSqlCommand("parameterlist.xml", oConn))
{
try { oConn.Open(); }
catch (Exception ex)
{
p_nErrorCode = 10;
p_sErrorMessage = "Error opening DB conenction during .DBLoadByID:
" + ex.Message;
goto Failed;
}
oCommand.Parameters["@objectid"].Value = new Guid(sID);
oCommand.Parameters["@authorityid"].Value = p_gAuthorityID;

try { oCommand.ExecuteNonQuery(); }
catch (Exception ex)
{
p_nErrorCode = 10;
p_sErrorMessage = "Sql exception during LoadByID: " + ex.Message;
goto Failed;
}
if (Convert.IsDBNull(oCommand.Parameters["@rowcount"].Value))
{
p_nErrorCode = 10;
p_sErrorMessage = "Null rowcount during LoadByID.";
goto Failed;
}

int nEffect =
Convert.ToInt32(oCommand.Parameters["@rowcount"].Value);
if (nEffect == 1)
{
p_gID = new Guid(sID);
p_dtDateCreated =
GetDateTimeParameter(oCommand.Parameters["@datecreated"]);
p_dtDateModified =
GetDateTimeParameter(oCommand.Parameters["@datemodified"]);
p_gModifiedBy = (Guid)oCommand.Parameters["@modifiedby"].Value;

p_bLoaded = true;
}
else
{
p_nErrorCode = 10;
p_sErrorMessage = "Unexpected rowcount (" + nEffect + ") during
LoadByID.";
goto Failed;
}
Failed:
if (ErrorCode > 0) bReturn = false;
}
return bReturn;
}
and here is the stuff behind the function call above
"CreateSqlCommand":

public SqlCommand CreateSqlCommand(string sFileName, SqlConnection
oConn)
{
XMLCommand oXMLCommand = new XMLCommand();
SqlCommand oCommand = oXMLCommand.CreateSqlCommand(sFileName);
if (oCommand == null)
{
p_nErrorCode = oXMLCommand.ErrorCode;
p_sErrorMessage = oXMLCommand.ErrorMessage;
return null;
}
oCommand.Connection = oConn;
return oCommand;
}

and here is the stuff behind the XMLCommand.CreateSqlCommand method:

public SqlCommand CreateSqlCommand(string sFileName)
{
p_nErrorCode = 0;
p_sErrorMessage = "";

SerializedParameters oSP = null;
XmlSerializer oSerializer = new
XmlSerializer(typeof(SerializedParameters));

oSerializer.UnknownNode += new XmlNodeEventHandler(this.UnknownNode);
oSerializer.UnknownAttribute += new
XmlAttributeEventHandler(this.UnknownAttribute);

try
{
using (FileStream oFS = new FileStream(p_sXmlPath + sFileName,
FileMode.Open, FileAccess.Read, FileShare.Read))
{
oSP = (SerializedParameters) oSerializer.Deserialize(oFS);
oFS.Close();
}
}
catch(Exception ex)
{
p_nErrorCode = 10;
p_sErrorMessage = "Error accessing or serializing XML document: " +
ex.Message;
goto Failed;
}
oSerializer = null;
Failed:
if (ErrorCode > 0) return null;
return oSP.CreateSqlCommand();
}

so is there anything in here that looks like it would likely cause a
memory leak? many thanks for the scrutiny and suggestions.

jason

Nov 30 '05 #2
> First, it appears that the using statement near the top for your SqlConnection
doesn't have anything "inside it".
if i'm not mistaken, that syntax is identical to nesting using
statements.

using (Object obj1)
using (Object obj2)
{
...
}

is the same thing as saying

using (Object obj1)
{
using (Object obj2)
{
...
}
}
The other pattern I see is that you have a bunch of try statments with no
closing Finally statement in which one would normally close a connection.
ahh, that does sound like a problem. so the garbage collection built
into the using statement won't clean up an unclosed connection? i would
need to close the connection inside the catch blocks, THEN the using
statement should clean up the connections?

that does sound like a very likely culprit, i will give it a shot.
I'd refactor the whole thing, and get rid of the "GOTO's".


oh believe me, we can't wait to do that. as soon as we can convince
management to let us do a .NET conversion of the consuming
applications, we can throw exceptions like a sane object library.

thanks,

jason

Nov 30 '05 #3
On 30 Nov 2005 07:55:20 -0800, "jason" <ia****@yahoo.com> wrote:
my w3wp.exe process has recently gotten an ever-expanding memory
footprint. the two most likely causes are either a memory leak in the
object library it uses, or session variables not getting cleaned up
correctly. this post is to check one thing in the object library, to
make sure that the "using" statement is being used correctly.
You seem to be using the using statement correctly. Using will always
make sure that the object is disposed when the leaving the using
statement scope.

Note: Disposing of the SqlConnection will automatically cause the
SqlCommand to be disposed so you don't have to call disposable on
both, only on the container (SqlConnection).

yes, i know that the use of error messaging is inadvisable and
unnecessary in .NET languages. we do plan to migrate this to use
exceptions in the future, however right now 90% of the consumers of
this object library are non.NET applications which cannot handle the
.NET exception classes.


Given the constraints that you have to use errorcodes/strings, I would
program it in the following way.

First, I wouldn't use multiple try-catch statements to create specific
error messages. It makes the code much less readably. It is in most
cases better to just rely on the exception message.

Second, while using is good syntactic sugar and does dispose of the
connections, in this case due to the need to handle error codes, I
would recommend using the more generic try-catch-finally.

The following code is a good way to program it. It simplifies program
flow and removes the need for goto by taking advantage of of
exceptions.

public override bool LoadByID(string sID, string sConnection)
{
// This is weakest point of the method that I could see.
// You are returning false, but not setting an error code or error.
// Why is Guid.Empty handled differently from all other exceptions?
if (AuthorityID = Guid.Empty) return false;

// Needs to be outside since it is needed in finally
SqlConnection oConn = null;
try
{
oConn = new SqlConnection(sConnection);
SqlCommand oCommand = this.CreateSqlCommand("parameterlist.xml",
oConn);

oConn.Open();
oCommand.Parameters["@objectid"].Value = new Guid(sID);
oCommand.Parameters["@authorityid"].Value = p_gAuthorityID;
oCommand.ExecuteNonQuery();

if (Convert.IsDBNull(oCommand.Parameters["@rowcount"].Value))
throw new ApplicationException("Null rowcount during
LoadByID.");

int nEffect =
Convert.ToInt32(oCommand.Parameters["@rowcount"].Value);

if (nEffect != 1)
throw new ApplicationException("Unexpected rowcount (" + nEffect
+ ") during LoadByID.");
p_gID = new Guid(sID);
p_dtDateCreated =
GetDateTimeParameter(oCommand.Parameters["@datecreated"]);
p_dtDateModified =
GetDateTimeParameter(oCommand.Parameters["@datemodified"]);
p_gModifiedBy = (Guid)oCommand.Parameters["@modifiedby"].Value;
p_bLoaded = true;

//Ugly, but required since you aren't allowed to throw exceptions
p_nErrorCode = 0;
p_sErrorMessage = "";
return true;
}
catch (Exception ex)
{
p_nErrorCode = 10;
p_sErrorMessage = ex.Message;
return false;
}
finally
{
//Make sure that the connection is disposed in all cases
if(oConn != null)
oConn.Dispose();
}
}

--
Marcus Andrén
Dec 1 '05 #4
Thank you very, very much Marcus. That might be the most useful
response I've gotten on usenet.

Jason

Dec 5 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Debian User | last post by:
Hi, I'm trying to discover a memory leak on a program of mine. I've taken several approaches, but the leak still resists to appear. First of all, I've tried to use the garbage collector to...
2
by: Elbert Lev | last post by:
#When I'm running this script on my windows NT4.0 box, #every time dialog box is reopened there is memory growth 384K. #Bellow is the text I sent to Stephen Ferg (author of easygui) # I have...
32
by: John | last post by:
Hi all: When I run my code, I find that the memory that the code uses keeps increasing. I have a PC with 2G RAM running Debian linux. The code consumes 1.5G memory by the time it finishes...
8
by: ranjeet.gupta | last post by:
Dear All Is the Root Cause of the Memory corruption is the Memory leak, ?? suppose If in the code there is Memory leak, Do this may lead to the Memory Corruption while executing the program ? ...
17
by: José Joye | last post by:
Hi, I have implemented a Service that is responsible for getting messages from a MS MQ located on a remote machine. I'm getting memory leak from time to time (???). In some situation, it is...
7
by: Salvador | last post by:
Hi, I am using WMI to gather information about different computers (using win2K and win 2K3), checking common classes and also WMI load balance. My application runs every 1 minute and reports...
3
by: Jim Land | last post by:
Jack Slocum claims here http://www.jackslocum.com/yui/2006/10/02/3-easy-steps-to-avoid-javascript- memory-leaks/ that "almost every site you visit that uses JavaScript is leaking memory". ...
7
by: Ragnar Agustsson | last post by:
Hi all I have been wandering about the best way to sandbox memory leaks in 3rd party libraries when using them from the .Net framework. I have a 3rd party library, written in C++, that leaks a...
22
by: Peter | last post by:
I am using VS2008. I have a Windows Service application which creates Crystal Reports. This is a multi theaded application which can run several reports at one time. My problem - there is a...
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
0
by: kcodez | last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
5
by: DJRhino | last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer) If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _ 310030356 Or 310030359 Or 310030362 Or...
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.