Memory Leaks!!!
---------------

                 Key: DNET-179
                 URL: http://tracker.firebirdsql.org/browse/DNET-179
             Project: .NET Data provider
          Issue Type: Bug
          Components: ADO.NET Provider
    Affects Versions: 2.1.0
         Environment: Windows XP (ANY), Windows Vista HE SP1, Core 2 Duo, 4Gb 
RAM, .NET 2.0, 3.5
            Reporter: Sergey Merkushov
            Assignee: Jiri Cincura
            Priority: Critical


Researching posible application memory leaks throow .NET Memory Profiler. 
Application use FirebirdClient 2.1 (included in application with source codes).
.NET Memory Profiler shows that after some time of working in memory more 
undisposed objects - as MemoryStreams, XdrStreams and others.

Below code - is my own desition of leaks, may it wrong? but it works for me. 
Please check it.

There are leaks in GdsTransaction and others that is not included in this post.

Best Regards.

List of Memery Leaks:
-----------------------------

1. FirebirdSql.Data.Client.Gds.XdrStream

public XdrStream(Stream innerStream, Charset charset) : base()
{
        this.buffer                     = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 
};
        this.innerStream        = innerStream;
        this.charset            = charset;
        
        // !!! posible is no need
        // GC.SuppressFinalize(innerStream);
}

if GC suppressed innerStream - the XdrStream is not disposed!!!

2. FirebirdSql.Data.Client.Gds.GdsStatement.Execute()

...
if (this.parameters != null)
{
        XdrStream xdr = new XdrStream(this.db.Charset);
        xdr.Write(this.parameters);

        descriptor = xdr.ToArray();

        xdr.Close();
        // !!! must be disposed !!!
        xdr.Dispose();
        xdr = null;
}
...

2. xdr.ToArray();

FirebirdSql.Data.Common.Descriptor.ToBlrArray()

MemoryStream blr - leak!!! Must be Disposed
See the end of method.

                public byte[] ToBlrArray()
                {
                        MemoryStream blr = new MemoryStream();
                        int par_count = this.Count * 2;

                        blr.WriteByte(IscCodes.blr_version5);
                        blr.WriteByte(IscCodes.blr_begin);
                        blr.WriteByte(IscCodes.blr_message);
                        blr.WriteByte(0);
                        blr.WriteByte((byte)(par_count & 255));
                        blr.WriteByte((byte)(par_count >> 8));

                        for (int i = 0; i < this.fields.Length; i++)
                        {
                                int dtype   = this.fields[i].SqlType;
                                int len     = this.fields[i].Length;

                                switch (dtype)
                                {
                                        case IscCodes.SQL_VARYING:
                                                
blr.WriteByte(IscCodes.blr_varying);
                                                blr.WriteByte((byte)(len & 
255));
                                                blr.WriteByte((byte)(len >> 8));
                                                break;

                                        case IscCodes.SQL_TEXT:
                                                
blr.WriteByte(IscCodes.blr_text);
                                                blr.WriteByte((byte)(len & 
255));
                                                blr.WriteByte((byte)(len >> 8));
                                                break;

                                        case IscCodes.SQL_DOUBLE:
                                                
blr.WriteByte(IscCodes.blr_double);
                                                break;

                                        case IscCodes.SQL_FLOAT:
                                                
blr.WriteByte(IscCodes.blr_float);
                                                break;

                                        case IscCodes.SQL_D_FLOAT:
                                                
blr.WriteByte(IscCodes.blr_d_float);
                                                break;

                                        case IscCodes.SQL_TYPE_DATE:
                                                
blr.WriteByte(IscCodes.blr_sql_date);
                                                break;

                                        case IscCodes.SQL_TYPE_TIME:
                                                
blr.WriteByte(IscCodes.blr_sql_time);
                                                break;

                                        case IscCodes.SQL_TIMESTAMP:
                                                
blr.WriteByte(IscCodes.blr_timestamp);
                                                break;

                                        case IscCodes.SQL_BLOB:
                                                
blr.WriteByte(IscCodes.blr_quad);
                                                blr.WriteByte(0);
                                                break;

                                        case IscCodes.SQL_ARRAY:
                                                
blr.WriteByte(IscCodes.blr_quad);
                                                blr.WriteByte(0);
                                                break;

                                        case IscCodes.SQL_LONG:
                                                
blr.WriteByte(IscCodes.blr_long);
                                                
blr.WriteByte((byte)this.fields[i].NumericScale);
                                                break;

                                        case IscCodes.SQL_SHORT:
                                                
blr.WriteByte(IscCodes.blr_short);
                                                
blr.WriteByte((byte)this.fields[i].NumericScale);
                                                break;

                                        case IscCodes.SQL_INT64:
                                                
blr.WriteByte(IscCodes.blr_int64);
                                                
blr.WriteByte((byte)this.fields[i].NumericScale);
                                                break;

                                        case IscCodes.SQL_QUAD:
                                                
blr.WriteByte(IscCodes.blr_quad);
                                                
blr.WriteByte((byte)this.fields[i].NumericScale);
                                                break;
                                }

                                blr.WriteByte(IscCodes.blr_short);
                                blr.WriteByte(0);
                        }

                        blr.WriteByte(IscCodes.blr_end);
                        blr.WriteByte(IscCodes.blr_eoc);

                        // !!! resault
                        byte [] res = blr.ToArray();
                        // !!! blr must be disposed !!!
                        blr.Dispose();

                        return res;
                }

4. ParameterBuffer posible has to Destructor to release stream field.

class ParameterBuffer

...

        ~ParameterBuffer()
        {
                Dispose();
        }
        
        public void Dispose()
        {
            if (this.stream != null)
            {
                this.stream.Close();
                this.stream.Dispose();
            }
        }

5. FirebirdSql.Data.Client.Gds.GdsDatabase.Identify(string database)

MemoryStream user_id - memory leak!!! must be disposed!!!

                // !!! must be closed and disposed !!!
                user_id.Close();
                user_id.Dispose();

6. GdsConnection.Disconnect()

the XdrStreams - send and receive must be disposed, but can not becouse it has 
been GC supressed,

in Disconnect we can GC.ReRegisterForFinalize disposed objects

                public void Disconnect()
                {
                        try
                        {
                                if (this.receive != null)
                                {
                                        GC.ReRegisterForFinalize(this.receive);
                                        this.receive.Close();
                                        this.receive.Dispose();
                                }
                                if (this.send != null)
                                {
                                        GC.ReRegisterForFinalize(this.send);
                                        this.send.Close();
                                        this.send.Dispose();
                                }
                                if (this.networkStream != null)
                                {
                                        this.networkStream.Close();
                                }
                                if (this.socket != null)
                                {
                                        this.socket.Close();
                                }

                                this.receive            = null;
                                this.send                       = null;
                                this.socket                     = null;
                                this.networkStream      = null;
                        }
                        catch (IOException)
                        {
                                throw;
                        }
                }



-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://tracker.firebirdsql.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Firebird-net-provider mailing list
Firebird-net-provider@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/firebird-net-provider

Reply via email to