Potential dbi memory leak.

Steve Cookson - gmail <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.dbi.general
Message-ID <[email protected]>
Hi Guys,

You may have seen part of this post on PerlMonks.  If so apologies for 
the duplication.  This started off as a general search for leaks in my 
code, and resulted in a few hits, one of which was attached to every 
database access.

A simple "select ATT_RECORD_NAME_TXT from TBL_TEST; " results in the 
leak of one scalar value.  It seems to be attached to the ->prepare 
statement.

At first I assumed it was down to my Firebird driver, which is 
relatively new, so I switched the driver to ODBC::Firebird, with the 
same result.  Finally I changed to mysql and again got a memory leak.  
The only thing I can assume is that either my code is generically wrong 
(and I hope this is the case), or there is a leak in dbi, which I would 
be surprised by.

I would appreciate some advice.

Test code follows.  Please install Devel::Leak to pick up leaked scalars 
and update the dsn to the dsn of your choice.

Thanks for your help.

Regards,

Steve.

#! /usr/bin/perl

package main;
use strict;
use warnings;
use DBI;
#use DBD::Firebird;
use DBD::ODBC;
use Devel::Leak;
     my $handle;
     my $count_start;
     my $count_stop;
     my $gl_dbh;

     # Just do this 5 times to make sure there is no contribution to 
$handle count from Devel::Leak
     for (1..10){
     print "Handle init: ", Devel::Leak::NoteSV($Launch::handle),"\n";
     }
#my $loc_dsn = <<DSN;
#dbi:ODBC:Driver=Firebird;Dbname=/home/image/Documents/Endoscopia/DB/newEndo.fdb;
#ib_dialect=3;
#DSN
my $loc_dsn = <<DSN;
DBI:mysql:database=new_schema_test;
host=localhost;
port=3306";
DSN
     $Launch::gl_dbh=DBI->connect($loc_dsn,"root","password", {
         PrintError => 1,                    # Report errors via warn
         RaiseError => 1                    # Report errors via Die
     }
     ) or die;

     my @loc_sql_string =();
     $loc_sql_string[0]="CREATE TABLE TBL_TEST_LEAK ( ATTR_RECORD_ID_TXT 
VARCHAR(10) NOT NULL, ATT_RECORD_NAME_TXT VARCHAR(255), CONSTRAINT 
PK_TBL_TEST_LEAK PRIMARY KEY (ATTR_RECORD_ID_TXT) ); ";
     $loc_sql_string[1]="GRANT DELETE, INSERT, REFERENCES, SELECT, 
UPDATE ON TBL_TEST_LEAK TO  SYSDBA WITH GRANT OPTION";
     $loc_sql_string[2]="INSERT INTO TBL_TEST_LEAK (ATTR_RECORD_ID_TXT, 
ATT_RECORD_NAME_TXT) VALUES ('206', 'Delay Test 1' )";
     $loc_sql_string[3]="select ATT_RECORD_NAME_TXT from TBL_TEST_LEAK; ";
     $loc_sql_string[4]= $loc_sql_string[3];
     $loc_sql_string[5]= $loc_sql_string[3];
     $loc_sql_string[6]= $loc_sql_string[3];
     $loc_sql_string[7]= $loc_sql_string[3];
     $loc_sql_string[8]= $loc_sql_string[3];
     $loc_sql_string[9]="drop table TBL_TEST_LEAK; ";

     for (my $i=1;$i<=9;$i++){
     $count_start=Devel::Leak::NoteSV($Launch::handle);
     print "DBD start: ", $count_start,"\n";
     print $loc_sql_string[$i], "\n";
     dbd_select($loc_sql_string[$i]);
     # You can use
     #$count_stop=Devel::Leak::CheckSV($Launch::handle);
     $count_stop=Devel::Leak::NoteSV($Launch::handle);
     print "Handle stop: ", $count_stop,"\n";
     print "Count difference: ", $count_stop-$count_start,"\n";
     }
     $Launch::gl_dbh->disconnect;

sub dbd_select{
     my $loc_sql_string=shift;
     my $loc_sth=$Launch::gl_dbh->prepare($loc_sql_string) or die;
     #$loc_sth->execute() or die;
     #$loc_sth->finish();
     return;
}

1;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.