Bug in debugger (or my code): Bizarre copy of ARRAY...

V

vnick

Hi,

(before I start, sorry for the length of this posting)
I have this code (test case):
--------------------------------------------------------
#!/usr/local/bin/perl

use strict;
use vars qw ($d %spec %spec_cc);

# Nested Hash/Array hierarchy:
%spec = (
RIF_SOURCE_WIDTH => {
FMT => {genrule => "0x20", },
WIDTH => {genrule => "look_up(FMT)",
FMT => {
10 => "mul(ORIG_WIDTH,4)",
20 => "sub(ORIG_WIDTH,1)",
_OTHER_ => "sub(mul(int(div(ORIG_WIDTH,2)),2),1)",
_RANGE_ => [0,3, "and(ORIG_WIDTH,~3)"], #
},
},
},
);

######################################################################
# MAIN:

print ">>> " . $spec{RIF_SOURCE_WIDTH}{WIDTH}{FMT}{_RANGE_} . "\n";
local $d = 0;
%spec_cc = ();
&struct_copy (\%spec, \%spec_cc);
print "### " . $spec_cc{RIF_SOURCE_WIDTH}{WIDTH}{FMT}{_RANGE_} . "\n";
print "### " . $spec_cc{RIF_SOURCE_WIDTH}{WIDTH}{FMT}{_RANGE_}[2] .
"\n";

######################################################################
sub struct_copy {

my ($oref, $cref) = @_;
my $objkey; # indexing var.
my $ret = 0; # Return value.
$d++;

if (ref($oref) eq "HASH") {
foreach $objkey (keys(%$oref)) {
printf "H-key($d): %-20s \t[$oref -> $cref]\n",$objkey;
if (ref($$oref{$objkey}) eq "HASH") {
$$cref{$objkey} = ({}); # Generate empty hash hierarchy.
&struct_copy ($$oref{$objkey},$$cref{$objkey} );
}
elsif (ref($$oref{$objkey}) eq "ARRAY") {
$$cref{$objkey} = ([]); # Generate empty array hierarchy.
&struct_copy ($$oref{$objkey},$$cref{$objkey} );
}
elsif (ref($$oref{$objkey}) eq "SCALAR" || ref($$oref{$objkey})
eq "") {
$$cref{$objkey} = $$oref{$objkey};
}
else {
warn "ERROR: Only deep hashes or arrays or a mix of them can be
copied\n";
$ret = 1;
}
}
}
elsif (ref($oref) eq "ARRAY") {
for ($objkey = 0; $objkey <= $#{@$oref}; $objkey++) {
printf "A_Ind($d): %-20s \t[$oref -> $cref]\n", $objkey;
if (ref($$oref[$objkey]) eq "HASH") {
$$cref[$objkey] = ({}); # Generate empty hash hierarchy.
&struct_copy ($$oref[$objkey],$$cref[$objkey] );
}
elsif (ref($$oref[$objkey]) eq "ARRAY") {
$$cref[$objkey] = ([]); # Generate empty array hierarchy.
&struct_copy ($$oref[$objkey],$$cref[$objkey] );
}
elsif (ref($$oref[$objkey]) eq "SCALAR" || ref($$oref[$objkey])
eq "") {
$$cref[$objkey] = $$oref[$objkey];
}
else {
warn "ERROR: Only deep hashes or arrays or a mix of them can be
copied\n";
$ret = 1;
}
}
return $ret;
}
else {
warn "ERROR: Object $$oref is neither array nor hash!\n";
$ret = 1;
}
$d--;
return $ret;
}

---------------------------------------------------------------

sub struct_copy is to copy any combination of Hashes and Arrays
(probably obvious to most readers :).

My problem is now that this piece of code works fine -
but only as long as I do not use the debugger!

Running the code without debugger gives:

----------------------------------------------------------------
H-key(1): RIF_SOURCE_WIDTH [HASH(0x4006bec0) -> HASH(0x4006bee4)]
H-key(2): WIDTH [HASH(0x4009b590) -> HASH(0x4009b5b4)]
H-key(3): FMT [HASH(0x4009b560) -> HASH(0x4009b818)]
H-key(4): _OTHER_ [HASH(0x4005d5c8) -> HASH(0x40058f2c)]
H-key(4): _RANGE_ [HASH(0x4005d5c8) -> HASH(0x40058f2c)]
A_Ind(5): 0 [ARRAY(0x4003f7fc) ->
ARRAY(0x400591a8)]
A_Ind(5): 1 [ARRAY(0x4003f7fc) ->
ARRAY(0x400591a8)]
A_Ind(5): 2 [ARRAY(0x4003f7fc) ->
ARRAY(0x400591a8)]
H-key(5): 10 [HASH(0x4005d5c8) -> HASH(0x40058f2c)]
H-key(5): 20 [HASH(0x4005d5c8) -> HASH(0x40058f2c)]
H-key(4): genrule [HASH(0x4009b560) -> HASH(0x4009b818)]
H-key(3): FMT [HASH(0x4009b590) -> HASH(0x4009b5b4)]
H-key(4): genrule [HASH(0x4003f6d0) -> HASH(0x40058f14)]
### ARRAY(0x400591a8)
### and(ORIG_WIDTH,~3)

--------------------------------------------------------------

After switching the debugger on:

--------------------------------------------------------------

Loading DB routines from perl5db.pl version 1.27
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(testtest.pl:7): %spec = (
main::(testtest.pl:8): RIF_SOURCE_WIDTH => {
H-key(1): RIF_SOURCE_WIDTH [HASH(0x402724d4) -> HASH(0x402724f8)]
H-key(2): WIDTH [HASH(0x4027662c) -> HASH(0x40337d04)]
H-key(3): FMT [HASH(0x4027605c) -> HASH(0x4031bc9c)]
H-key(4): _OTHER_ [HASH(0x40275e34) -> HASH(0x4005fdec)]
H-key(4): _RANGE_ [HASH(0x40275e34) -> HASH(0x4005fdec)]
Bizarre copy of ARRAY in leave at testtest.pl line 65.
at testtest.pl line 65
main::struct_copy('ARRAY(0x4003f5ec)', 'ARRAY(0x4006008c)')
called at testtest.pl line 53
main::struct_copy('HASH(0x40275e34)', 'HASH(0x4005fdec)')
called at testtest.pl line 49
main::struct_copy('HASH(0x4027605c)', 'HASH(0x4031bc9c)')
called at testtest.pl line 49
main::struct_copy('HASH(0x4027662c)', 'HASH(0x40337d04)')
called at testtest.pl line 49
main::struct_copy('HASH(0x402724d4)', 'HASH(0x402724f8)')
called at testtest.pl line 32
Debugged program terminated. Use q to quit or R to restart,
use O inhibit_exit to avoid stopping after program termination,
h q, h R or h O to get additional info.
DB<1>

---------------------------------------------------------------

So the question is why Perl (5.8.5) only reports this bizarre error
when I use the debugger?? Do I still have a bug in my code though it
works and I do not see where it could be or is that a debugger bug?

Any help appreciated - thanks!
Volker
 
P

Paul Lalli

Hi,

(before I start, sorry for the length of this posting)
I have this code (test case):

Why aren't you using warnings?
use vars qw ($d %spec %spec_cc);

Why are you using global variables?
Why are you using 'use vars' instead of 'our'?

local $d = 0;

Why are you localizing global variables instead of declaring lexicals?
%spec_cc = ();
&struct_copy (\%spec, \%spec_cc);

Why are you calling your subroutines with the ampersand?

Your code looks very much like Perl 4. I would suggest you head to
http://learn.perl.org and start learning Perl 5.
sub struct_copy is to copy any combination of Hashes and Arrays
(probably obvious to most readers :).

Why are you reinventing the wheel? Take a look at Data::Dumper, or
CPAN's Clone and Storable.
After switching the debugger on:
Bizarre copy of ARRAY in leave at testtest.pl line 65.
at testtest.pl line 65

Did you go to line 65 to see if there's anything wrong? I did...
for ($objkey = 0; $objkey <= $#{@$oref}; $objkey++) {

That should be $#{$oref}, not $#{@$oref}.

Now, I have no idea why they syntax you used doesn't report an error or
a warning, but fixing this line removes the error from the debugging
run.

.... and further examination reveals that Perl apparently allows both
versions of this syntax:

$ perl -le'my @foo=qw/a b c d/; print $#{@foo};'
3
$ perl -le'my @foo=qw/a b c d/; print $#{foo};'
3

That seems odd to me. I'd never seen the first version of this before
this post.
So the question is why Perl (5.8.5) only reports this bizarre error
when I use the debugger??

I have no idea about this either...
Do I still have a bug in my code though it works and I do not see where it
could be or is that a debugger bug?

Hard to call it a "bug" when it doesn't appear to affect the
functionality of the code, but I'd still say it's definately something
that should be fixed...

Paul Lalli
 
V

vnick

Thanks, Paul...

Paul said:
Did you go to line 65 to see if there's anything wrong? I did...


That should be $#{$oref}, not $#{@$oref}.

Why? $# says that it should give the last index of an array but $oref
is
a reference whereas @$oref is the array. So why is that wrong?
This is dereferencing the array reference, is it? And then taking the
array to get its last index!?

Volker
 
P

Peter Scott

Bizarre copy of ARRAY in leave at testtest.pl line 65. [snip]
So the question is why Perl (5.8.5) only reports this bizarre error
when I use the debugger?? Do I still have a bug in my code though it
works and I do not see where it could be or is that a debugger bug?

If you can reduce this to a *much* shorter example and demonstrate it on
the latest version of perl, please report it to the Perl 5 Porters list.
While bugs like this in the debugger are notoriously difficult to fix,
the bug report will be accepted. It should be impossible to get this
message by accident regardless of poor programming practices.
 
P

Paul Lalli

Why? $# says that it should give the last index of an array but $oref
is a reference whereas @$oref is the array. So why is that wrong?
This is dereferencing the array reference, is it? And then taking the
array to get its last index!?

$oref is the reference
@{$oref} is the array itself
${$oref}[0] is the first element
$#{$oref} is the last index.

This all follows "Use Rule 1" from
http://perldoc.perl.org/perlreftut.html#Using-References

'$oref' is the name of the array @{$oref}, just as 'foo' is the name of
the array @foo. To obtain the last index of an array, you prepend its
name with the '$#' characters.

As I said in my previous followup, it is clear that Perl does accept
the alternate syntax of prepending $# to the entire array, including
sigil (as in: $#@foo), but I have no idea why. (perldoc perldata,
which discusses the $# syntax, certainly doesn't mention it).

Paul Lalli
 
P

Paul Lalli

Peter said:
Bizarre copy of ARRAY in leave at testtest.pl line 65. [snip]
So the question is why Perl (5.8.5) only reports this bizarre error
when I use the debugger?? Do I still have a bug in my code though it
works and I do not see where it could be or is that a debugger bug?

If you can reduce this to a *much* shorter example and demonstrate it on
the latest version of perl, please report it to the Perl 5 Porters list.
While bugs like this in the debugger are notoriously difficult to fix,
the bug report will be accepted. It should be impossible to get this
message by accident regardless of poor programming practices.

#!/usr/bin/perl -d
use strict;
use warnings;

my $i;
my $aref = [1..10];
for ($i=0; $i<=$#{@$aref}; $i++){
print "$i: $aref->[$i]\n";
}

__END__

$ ./clpm.pl
Default die handler restored.

Loading DB routines from perl5db.pl version 1.07
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(./clpm.pl:5): my $i;
DB<1> c
Bizarre copy of ARRAY in leave at ./clpm.pl line 7.
Debugged program terminated. Use q to quit or R to restart,
use O inhibit_exit to avoid stopping after program termination,
h q, h R or h O to get additional info.
DB<1>


(I'll send this to the porters as well)

Paul Lalli
 
P

Paul Lalli

Previous program was not nearly as short as it could have been:

#!/usr/bin/perl
use strict;
use warnings;

my $i;
my @a = (1..10);

my $last = $#{@a};
print "Last index: $last\n";

__END__


Do note, however, that I am currently using 5.6.1. I'll test with a
more recent version when I leave work tonight.

Paul Lalli
 
V

vnick

Paul said:
$oref is the reference
@{$oref} is the array itself
${$oref}[0] is the first element
$#{$oref} is the last index.

This all follows "Use Rule 1" from
http://perldoc.perl.org/perlreftut.html#Using-References

'$oref' is the name of the array @{$oref}, just as 'foo' is the name of
the array @foo. To obtain the last index of an array, you prepend its
name with the '$#' characters.

If that is correct where is the difference then between a symbolic and
a hard reference in Perl?


Thanks again.
Volker
 
J

John W. Krahn

Paul said:
Why? $# says that it should give the last index of an array but $oref
is a reference whereas @$oref is the array. So why is that wrong?
This is dereferencing the array reference, is it? And then taking the
array to get its last index!?

$oref is the reference
@{$oref} is the array itself
${$oref}[0] is the first element
$#{$oref} is the last index.

This all follows "Use Rule 1" from
http://perldoc.perl.org/perlreftut.html#Using-References

'$oref' is the name of the array @{$oref}, just as 'foo' is the name of
the array @foo. To obtain the last index of an array, you prepend its
name with the '$#' characters.

As I said in my previous followup, it is clear that Perl does accept
the alternate syntax of prepending $# to the entire array, including
sigil (as in: $#@foo), but I have no idea why. (perldoc perldata,
which discusses the $# syntax, certainly doesn't mention it).

Apparently sometimes @array and array are synonymous, probably some backwards
compatibility thing.

$ perl -le' @x = 3..9; print $#{@x}'
6
$ perl -le' @x = 3..9; print $#x'
6
$ perl -le' @x = 3..9; print shift( x )'
3
$ perl -le' @x = 3..9; print shift( @x )'
3



John
 
P

Paul Lalli

Paul said:
$oref is the reference
@{$oref} is the array itself
${$oref}[0] is the first element
$#{$oref} is the last index.

This all follows "Use Rule 1" from
http://perldoc.perl.org/perlreftut.html#Using-References

'$oref' is the name of the array @{$oref}, just as 'foo' is the name of
the array @foo. To obtain the last index of an array, you prepend its
name with the '$#' characters.

If that is correct where is the difference then between a symbolic and
a hard reference in Perl?

.... what has any of this to do with symbolic vs hard references?

#!/usr/bin/perl
use strict '!refs';
use warnings;

our $foo = 'hello world';
my $hard = \$foo;
my $name = 'foo';
my $soft = ${$name};

print "Hard: $$hard\nSoft: $soft\n";

__END__

A hard reference is a variable that actually contains a reference to
another variable. A soft (or 'symbolic') reference is a variable that
contains the name of another variable.

http://perldoc.perl.org/perlref.html#Symbolic-references

Paul Lalli
 
J

Jeff Stampes

Paul said:
#!/usr/bin/perl
use strict;
use warnings;

my $i;
my @a = (1..10);

my $last = $#{@a};
print "Last index: $last\n";

__END__


Do note, however, that I am currently using 5.6.1. I'll test with a
more recent version when I leave work tonight.

Confirmed on a more modern perl:

This is perl, v5.8.6 built for i386-linux-thread-multi

~JEff
 
B

Babacio

Jeff Stampes.
Confirmed on a more modern perl:

This is perl, v5.8.6 built for i386-linux-thread-multi
Same symptom on:

This is perl, v5.8.7 built for darwin-thread-multi-2level
 
A

Anno Siegel

$ perl -le' @x = 3..9; print shift( x )'
3

Yikes!

It does give a syntax warning, however:

$ perl -wle '@x = 3..9; print shift( x )'
Unquoted string "x" may clash with future reserved word at -e line 1.
Array @x missing the @ in argument 1 of shift() at -e line 1.
3

Anno
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top