http://www.perlmonks.org?node_id=545221

marinersk has asked for the wisdom of the Perl Monks concerning the following question:

The questions will be:

  1. Why is this generating a diagnostic warning?
  2. What can I do about it?

I've inherited a huge thing that uses lots of dbmopen() and dbmclose(). I know this is now superceded by tie(), but I'd like to understand what is going on before I decide to go changing things willy-nilly.

The following snippet demonstrates something I'm running into when I turn on WARNINGS:

     
#!/usr/bin/perl -w use strict; my $TSTFNM = "test-dbm-data"; my $TSTACC = 0666; my $opnret = dbmopen(my %TSTDBM, $TSTFNM, $TSTACC); print "DBM Open: '$opnret'\n"; my $cloret = dbmclose(%TSTDBM); exit; __END__

I get the following results:

     
DBM Open: 'AnyDBM_File=SCALAR(0x1982e8c)' <BR>untie attempted while 1 inner references still exist at D:\Steve\D +ev\test-dbm.pl line 10.

If I take out the perl -w, no problems reported.

  1. Why is this generating a diagnostic warning?
  2. What can I do about it?

I've poked around Google and done a search here at PerlMonks and I'm landing on neither a useful problem description nor a useful solution.

So I thought I'd pray for divine intervention. :-)

Many thanks for your time and assistance.

- Steven K. Mariner

Replies are listed 'Best First'.
Re: Perl Warning On dbmclose()
by PodMaster (Abbot) on Apr 24, 2006 at 06:37 UTC
    Errors and warnings are documented in perldiag.
    untie attempted while %d inner references still exist
        (W untie) A copy of the object returned from tie (or tied) was still valid when untie was called.
    If you undef $opnret before you call dbmclose, that warning should go away.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      I was unable to relate the explanation from perldiag to what was hapenning with dbmopen()/dbmclose(). I suppose if I understood ties and understood how dbmopen() and dbmclose() were using ties, maybe that error message could have held some meaning for me. Since I lack that knowledge, there weren't any words in perldiag that actually mapped to what I was doing in any terms I could understand. :-(

      My limited exposure to object-oriented Perl, however, did give me the opportunity to eventually arrive at the instictive sense that perhaps the assignment on dbmopen() was causing a reference to hang around when the untie() was attempted. :-)

      Unfortunately that moment of discovery came just after I posted my question. :-(

      Thank you, however, for the information. I knew I'd find the answer here. :-)

      - Steve M.

Re: Perl Warning On dbmclose()
by davorg (Chancellor) on Apr 24, 2006 at 07:58 UTC

    It's probably worth pointing out that dbmopen and dbmclose are both really only there for backwards compatibility with older programs. For new code you should almost certainly be using tie and untie instead.

    If I take out the perl -w, no problems reported.

    How about that! You don't ask Perl to tell you about warnings and you don't get any warnings. Isn't technology wonderful :)

    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: Perl Warning On dbmclose()
by marinersk (Priest) on Apr 24, 2006 at 06:38 UTC
    NEVER MIND --

    Apparently, dbmopen() and dbmclose() were not intended to be used with return values in mind.

    Adding the 'undef' statement in following modified snippet solves the problem:

         
    #!/usr/bin/perl -w use strict; my $TSTFNM = "test-dbm-data"; # Test database base filename my $TSTACC = 0666; # Test database default a +ccess my $opnret = dbmopen(my %TSTDBM, $TSTFNM, $TSTACC); print "DBM Open: '$opnret'\n"; undef $opnret; my $cloret = dbmclose(%TSTDBM); exit; __END__

    Which means I can eliminate the assignment on the dbmopen() or do an undef before dbmclose().

    Sorry to disturb.

    - Steven K. Mariner