Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2007-09

Mem-leak, where?

4 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Joost van der Sluis

Hi all,

About bug 9751. I don't understand where the leak comes from. Take this code:

----
program testbug9751;
{$mode objfpc}{$H+}
uses
  Classes, SysUtils, mysql41dyn;
var hmysql : PMYSQL;
begin
//  InitialiseMysql; <-- remove the comment and the leakage is gone
  repeat
  InitialiseMysql;
  hmysql := nil;
  hmysql := mysql_init(hmysql);
// Comment the next line and the leakage is gone
  HMySQL:=mysql_real_connect(HMySQL,PChar(''),PChar(''),Pchar(''),Nil,0,Nil,0);
  mysql_close(hmysql);
  ReleaseMysql;
  until 1<0;
end.
----

This code leaks memory very fast. ;) First I thought that the InitialiseMysql and ReleaseMysql were leaking. If you remove the first comment, the leakage is gone. This is because the refcount of the MySQL-library is increased, so that the library isn't loaded anymore inside the loop.

But the strange thing is, that if you remove the mysql_real_connect, the leakage is also gone.

Thus: the InitialiseMySQL and ReleaseMySQL (probably loadlibrary, unloadlibrary and GetProcedureAddress) procedures are leaking memory, but only if the library is called in between them. (not all functions, but some of them)

Any ideas?

Joost.

Reply by email

Sergei Gorelkin
to Joost van der Sluis
Joost van der Sluis wrote 23 lines
---- program testbug9751; {$mode objfpc}{$H+} uses Classes, SysUtils, mysql41dyn; var hmysql : PMYSQL; begin // InitialiseMysql; <-- remove the comment and the leakage is gone repeat InitialiseMysql; hmysql := nil; hmysql := mysql_init(hmysql); // Comment the next line and the leakage is gone HMySQL:=mysql_real_connect(HMySQL,PChar(''),PChar(''),Pchar(''),Nil,0,Nil,0); mysql_close(hmysql); ReleaseMysql; until 1<0; end. ----

Looks like mysql_real_connect() overwrites hmysql variable? The value returned by mysql_init() is not passed to mysql_close(), and the library may not unload in this case.
If you comment mysql_real_connect(), handle returned by mysql_init() IS passed to mysql_close().

Sergei

Reply by email

Joost van der Sluis
to Sergei Gorelkin

Op woensdag 26-09-2007 om 02:29 uur [tijdzone +0400], schreef Sergei Gorelkin:

Show quoted text 30 lines
Joost van der Sluis wrote: > ---- > program testbug9751; > > {$mode objfpc}{$H+} > > uses > Classes, SysUtils, mysql41dyn; > > var hmysql : PMYSQL; > > begin > // InitialiseMysql; <-- remove the comment and the leakage is gone > repeat > InitialiseMysql; > hmysql := nil; > hmysql := mysql_init(hmysql); > // Comment the next line and the leakage is gone > HMySQL:=mysql_real_connect(HMySQL,PChar(''),PChar(''),Pchar(''),Nil,0,Nil,0); > mysql_close(hmysql); > ReleaseMysql; > until 1<0; > end. > ---- Looks like mysql_real_connect() overwrites hmysql variable? The value returned by mysql_init() is not passed to mysql_close(), and the library may not unload in this case. If you comment mysql_real_connect(), handle returned by mysql_init() IS passed to mysql_close().

I also thought that. But that's not the case. From the mysql-documentation:
(http://dev.mysql.com/doc/refman/5.0/en/mysql-real-connect.html)

----
Return Values

A MYSQL* connection handle if the connection was successful, NULL if the connection was unsuccessful. For a successful connection, the return value is the same as the value of the first parameter. ----

Also in the case of a succesfull connection, this code leaks...

I've rewritten the code, so that it's more clear what happens: -----
program testbug9751;

{$mode objfpc}{$H+}
uses
  Classes, SysUtils, mysql41dyn,dynlibs;
var hmysql : PMYSQL;
    LH : TLibHandle;
begin
  repeat // repeat here gives troubles
  LH := loadlibrary(mysqllib);
  pointer(mysql_init) := GetProcedureAddress(LH,'mysql_init');
  pointer(mysql_real_connect) := GetProcedureAddress(LH,'mysql_real_connect');
  pointer(mysql_close) := GetProcedureAddress(LH,'mysql_close');
// repeat; <- if the repeat is placed here, the problems are gone
  hmysql := nil;
  hmysql := mysql_init(hmysql);
// Remove the next line and the problem is gone.
  HMySQL:=mysql_real_connect(HMySQL,PChar('192.168.3.1'),PChar('root'),Pchar('rosivrepus'),Nil,0,Nil,0);
  mysql_close(hmysql);
//  until 1<0; <- if the until is placed here, the problems are gone
  UnloadLibrary(LH);
  until 1<0; // until here gives troubles
end.
-----

so you can solve the leak by two ways:
1: remove the mysql_real_connect
2: move the repeat-until so that the 'initialisation' is outside the loop

Joost.

Reply by email

Michael Van Canneyt
to Joost van der Sluis
Joost van der Sluis wrote 83 lines
Op woensdag 26-09-2007 om 02:29 uur [tijdzone +0400], schreef Sergei Gorelkin: > Joost van der Sluis wrote: > > ---- > > program testbug9751; > > > > {$mode objfpc}{$H+} > > > > uses > > Classes, SysUtils, mysql41dyn; > > > > var hmysql : PMYSQL; > > > > begin > > // InitialiseMysql; <-- remove the comment and the leakage is gone > > repeat > > InitialiseMysql; > > hmysql := nil; > > hmysql := mysql_init(hmysql); > > // Comment the next line and the leakage is gone > > HMySQL:=mysql_real_connect(HMySQL,PChar(''),PChar(''),Pchar(''),Nil,0,Nil,0); > > mysql_close(hmysql); > > ReleaseMysql; > > until 1<0; > > end. > > ---- > > Looks like mysql_real_connect() overwrites hmysql variable? The value > returned by mysql_init() is not passed to mysql_close(), and the library > may not unload in this case. > If you comment mysql_real_connect(), handle returned by mysql_init() IS > passed to mysql_close(). I also thought that. But that's not the case. From the mysql-documentation: (http://dev.mysql.com/doc/refman/5.0/en/mysql-real-connect.html) ---- Return Values A MYSQL* connection handle if the connection was successful, NULL if the connection was unsuccessful. For a successful connection, the return value is the same as the value of the first parameter. ---- Also in the case of a succesfull connection, this code leaks... I've rewritten the code, so that it's more clear what happens: ----- program testbug9751; {$mode objfpc}{$H+} uses Classes, SysUtils, mysql41dyn,dynlibs; var hmysql : PMYSQL; LH : TLibHandle; begin repeat // repeat here gives troubles LH := loadlibrary(mysqllib); pointer(mysql_init) := GetProcedureAddress(LH,'mysql_init'); pointer(mysql_real_connect) := GetProcedureAddress(LH,'mysql_real_connect'); pointer(mysql_close) := GetProcedureAddress(LH,'mysql_close'); // repeat; <- if the repeat is placed here, the problems are gone hmysql := nil; hmysql := mysql_init(hmysql); // Remove the next line and the problem is gone. HMySQL:=mysql_real_connect(HMySQL,PChar('192.168.3.1'),PChar('root'),Pchar('rosivrepus'),Nil,0,Nil,0); mysql_close(hmysql); // until 1<0; <- if the until is placed here, the problems are gone UnloadLibrary(LH); until 1<0; // until here gives troubles end. ----- so you can solve the leak by two ways: 1: remove the mysql_real_connect 2: move the repeat-until so that the 'initialisation' is outside the loop

That points to a memory leak in libmysqlclient itself, no ? Maybe it is not meant to be loaded/unloaded ?

Michael.

Reply by email