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