Re: Memory leak in DBI ?

"Philippe Bruhat (BooK)" <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.dbi.sybase.devel
Message-ID <[email protected]>
On Thu, Apr 10, 2008 at 03:40:55PM +0100, Tim Bunce wrote:
> I trust the script is destroying the results and, where appropriate,
> the $sth before calling Devel::Leak::CheckSV.

Yes.

The command is run in a block, with lexicals (except the $dbh).
To avoid counting information that is retained by the DBI, the command
is run twice, and the leak count is done on the second run only.

> Could you post the script?

It was attached to my email, but the mailing list manager seem to have
eaten it.

Here it is:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    use DBI;
    use Devel::Leak;
    use Test::More;
    
    # some dsn configuration
    my %dsn = (
        sqlite => [ 'dbi:SQLite:dbname=test.sql', '', '' ],
        mysql  => [ 'dbi:mysql:test',             '', '' ],
        csv    => [ 'dbi:CSV:',                   '', '' ],
    );
    
    # generic SQL
    my %SQL = (
        drop   => 'DROP TABLE IF EXISTS tok',
        create => 'CREATE TABLE tok (kuk INT, zat INT, sob TEXT)',
        insert => 'INSERT INTO tok (kuk, zat, sob) VALUES (?,?,?)',
        select => 'SELECT kuk, zat, sob FROM tok',
    );
    
    my @tests = (
        q{my $sanity = 1;},    # simple sanity test (eval "" doesn't leak)
    q{my $s = $dbh->prepare( $sql ); $s->execute(); 1 while $s->fetchrow_arrayref(); $s->finish;},
    q{my $s = $dbh->prepare_cached( $sql ); $s->execute(); 1 while $s->fetchrow_arrayref(); $s->finish;},
        q{my $c = $dbh->selectcol_arrayref( $sql, { Column => [1] } )},
        q{my @a = $dbh->selectrow_array( $sql )},
        q{my $a = $dbh->selectrow_arrayref( $sql )},
    );
    
    # plan
    plan tests => @tests * keys %dsn;
    
    for my $dbd ( sort keys %dsn ) {
    
      SKIP: {
    
            # connect to the test db
            my $dbh =
              eval { DBI->connect( @{ $dsn{$dbd} }, { RaiseError => 1 } ); };
    
            skip "Connection to $dbd failed: $@", scalar @tests if !$dbh;
    
            # initialize the table
            $dbh->do( $SQL{drop} );
            $dbh->do( $SQL{create} );
    
            # fill in some data
            my $sth;
            $sth = $dbh->prepare( $SQL{insert} );
            $sth->execute( $_, 100 - $_, 'x' x $_ ) for 1 .. 30;
    
            # test each command
            for my $cmd (@tests) {
    
                # get the SQL statement
                my $sql = $SQL{select};
    
                # run once, in case some internal structures get initialized
                eval $cmd;
    
                # now look for leakage
                my $c1 = Devel::Leak::NoteSV( my $h );
                {
                    eval $cmd;
                }
                my $c2 = Devel::Leak::CheckSV($h);
                diag $@ if $@;
    
                my $leak = $c2 - $c1;
                is( $leak, 0, sprintf "leak = $leak for %-8s%s", $dbd, $cmd );
            }
    
        }
    }


-- 
 Philippe Bruhat (BooK)

 When you allow legends to rule your life, your world is based on fiction.
                                    (Moral from Groo The Wanderer #99 (Epic))
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.