Use of uninitialized value in substitution (s///)

H

Hugh Lawson

This error occurs in this program. What is uninitialized in the substitution?

I've spent quite a while searching for clues.

#! /usr/bin/perl
use strict;
use warnings;
use diagnostics;
use GDBM_File;
my $db_file;
my %fred;
my $word;
my $defn;
my $db;

$db_file="frenchwords";
$db = tie %fred, 'GDBM_File', $db_file, &GDBM_WRCREAT, 0640;

# Install DBM Filters.

######Error comes on next line******************
$db->filter_fetch_key ( sub { s/\0$// } ) ;
$db->filter_store_key ( sub { $_ .= "\0" } ) ;
$db->filter_fetch_value( sub { s/\0$// } ) ;
$db->filter_store_value( sub { $_ .= "\0" } ) ;

while (($word, $defn) = each (%fred)) { print ("$word: $defn\n"); }

undef $db;
untie %fred;

#end of program.
 
J

John W. Krahn

Hugh said:
This error occurs in this program. What is uninitialized in the substitution?

I've spent quite a while searching for clues.

See the example code for 'filter_fetch_value' in the perldbmfilter man page.

perldoc perldbmfilter


John
 
H

Hugh Lawson

John W. Krahn said:
See the example code for 'filter_fetch_value' in the perldbmfilter man page.

perldoc perldbmfilter
Hi John,

Did you mean this line?

$db->filter_fetch_value(sub{no warnings 'uninitialized'; s/\0$//} ) ;


That stops the warning, but why is 'no warnings' needed? Why can't the
substitution be written to evade the warning? Is it "just one of
those things"?

And thanks for the reply.
 
A

Anno Siegel

Hugh Lawson said:
Hi John,

Did you mean this line?

$db->filter_fetch_value(sub{no warnings 'uninitialized'; s/\0$//} ) ;


That stops the warning, but why is 'no warnings' needed? Why can't the
substitution be written to evade the warning? Is it "just one of
those things"?

The substitution can do nothing to stop the warning. The warning happens
whenever you try to apply *any* substitution to an undefined value.

There is, of course, more than one way to silence the warning.

sub { s/\0$// if defined }

should work as well.

Anno
 
H

Hugh Lawson

The substitution can do nothing to stop the warning. The warning happens
whenever you try to apply *any* substitution to an undefined value.

There is, of course, more than one way to silence the warning.

sub { s/\0$// if defined }

should work as well.

Hello Anno,

Why is the substitution undefined? What in Perl is undefined about

s/\0$//

That's what I'm wondering about. From my earlier document-reading I
learned how to stifle the warning, but what evoked it?

To me 's/\0$//' says

take the variable $_, and if there is a \0 at the end,
remove it, leaving everything else in $_

How can the code work right if $_ is undefined?

Thanks for the reply.
 
A

Anno Siegel

Hugh Lawson said:
Hello Anno,

Why is the substitution undefined? What in Perl is undefined about

s/\0$//

Nothing is undefined about it, it's an operator.
That's what I'm wondering about. From my earlier document-reading I
learned how to stifle the warning, but what evoked it?

The warning happens when Perl tries to apply the perfectly legal s///
operator to the undefined variable $_ (*if* it is undefined).
To me 's/\0$//' says

take the variable $_, and if there is a \0 at the end,
remove it, leaving everything else in $_

How can the code work right if $_ is undefined?

Perl converts the undefined value to an empty string, if forced. It
does that here, finds that the empty string doesn't end with a "0" and
returns the empty string unchanged. That works perfectly well, but it
may not be what the programmer intended, hence the warning.

Anno
 
H

Hugh Lawson

Nothing is undefined about it, it's an operator.


The warning happens when Perl tries to apply the perfectly legal s///
operator to the undefined variable $_ (*if* it is undefined).


Perl converts the undefined value to an empty string, if forced. It
does that here, finds that the empty string doesn't end with a "0" and
returns the empty string unchanged. That works perfectly well, but it
may not be what the programmer intended, hence the warning.


Hello Anno,

Thank you for the reply. Perhaps we are communicating at cross
purposes. My point is that warning or not, the substitution seems to
work as expected.

To see what I'm talking about, search for this line

$db->filter_fetch_value(
sub { no warnings 'uninitialized' ;s/\0$// } ) ;

in perldoc perldbmfilter.

This is one of several recommended filters for use when perl accesses
and changes strings in db files that must also be available for C
programs.
 
A

Anno Siegel

Hugh Lawson said:
(e-mail address removed)-berlin.de (Anno Siegel) writes:
[...]
Perl converts the undefined value to an empty string, if forced. It
does that here, finds that the empty string doesn't end with a "0" and
returns the empty string unchanged. That works perfectly well, but it
may not be what the programmer intended, hence the warning.


Hello Anno,

Thank you for the reply. Perhaps we are communicating at cross
purposes. My point is that warning or not, the substitution seems to
work as expected.

How is that surprising? The purpose of the substitution is to get rid
of a trailing null byte in C strings. If $_ is undefined, the
substitution returns an empty string. That doesn't have a trailing null
byte, so the purpose of the substitution is attained.
To see what I'm talking about, search for this line

$db->filter_fetch_value(
sub { no warnings 'uninitialized' ;s/\0$// } ) ;

in perldoc perldbmfilter.

I don't have perldbmfilter around (is it really spelled that way?).
The code is the same as earlier in the thread. What's to discover?

Anno
 
P

Paul Lalli

Hugh said:
My point is that warning or not, the substitution seems to
work as expected.

$db->filter_fetch_value(
sub { no warnings 'uninitialized' ;s/\0$// } ) ;

How are you defining "work"? Do you understand what that substitution
is doing? It is taking the $_ variable, and searching for \0 (the null
byte) at the end of the string that $_ contains. If the null byte is
found there, it is removed from $_.

Since $_ is undefined, there is obviously no \0 to find and remove.
The subsitution operator does exactly what it's supposed to do in that
case: nothing.

Paul Lalli
 
H

Hugh Lawson

Paul Lalli said:
How are you defining "work"?

I use small test db files, type in the values, keeping the
number of records small enough that I know what to expect. I move the
db file back and forth between C and perl to check for consistent
results. (I'm learning GDBM_File and C libgdbm.) Once I learned how to
use the filters, I got consistent results, but the filter evoked the
warning in perl.
Do you understand what that substitution
is doing? It is taking the $_ variable, and searching for \0 (the null
byte) at the end of the string that $_ contains. If the null byte is
found there, it is removed from $_.

Yes.

In every case $_ should contain a null-terminated string as the data for
both key and value, because I've done the best I can to set up the db
file that way.
Since $_ is undefined, there is obviously no \0 to find and remove.
The subsitution operator does exactly what it's supposed to do in that
case: nothing.

It bothers me that $_ should be undefined, since I've tried hard to
make sure that every record in the db file has a null-terminated
string in both the key and the value.

Is it possible that the 'undefined value' warning is called forth by
an end-of-file or end-of-data event, after fetch has collected all the
stored records in the file?
 
T

Tad McClellan

Hugh Lawson said:
This error occurs in this program.


It is not an "error".

It is a "warning".

What is uninitialized in the substitution?

$_


######Error comes on next line******************
$db->filter_fetch_key ( sub { s/\0$// } ) ;


Where is the string that you are substituting against?

What value have you put in that string?
 
H

Hugh Lawson

Tad McClellan said:
Hugh Lawson <[email protected]> wrote:

[ snip ]

Change Error to warning.
Where is the string that you are substituting against?

What value have you put in that string?

The data contents of the gdbm data file "frenchwords".

The data consists of strings, the C-style strings with null
terminations. Below is a snip from the program.

$db_file="frenchwords";
$db = tie %fred, 'GDBM_File', $db_file, &GDBM_WRCREAT, 0640;

Since I typed the values of the data in the data files, I'm reasonably
confident, though not absolutely certain, there are no missing data
values. The program is meant to make sure that saved data strings
have null terminations to make them copacetic for C.

I can test for the null-terminations by opening the same gdbm data
file with a C program, which gets mixed up about the string
contents when there are no null-terminations.

Thanks for the reply.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,130
Latest member
MitchellTe
Top