Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Well, that's the most obscure Perl bug I've ever seen

27 views
Skip to first unread message

pete

unread,
Mar 11, 2010, 8:03:58 AM3/11/10
to

I was fixing a problem that "just appeared" in some otherwise working
code. There were no syntax errors and the program ran fine - it's just
that the result went from being correct to being uttterly and completely
wrong. A bit of lateral thinking and investigation solved the problem.
However, for your entertainment and education, here's a cut down version
that exhibts the same effect:

$

# set up a counter
$i = 0;

for($j = 0; $j < 10; $j++) {
print "j = $j\n";
$i++;
}
print "j = $j, i=$i\n";

which, when run produces:

root: perl bug.pl
j = 0
j = 1
j = 2
j = 3
j = 4
j = 5
j = 6
j = 7
j = 8
j = 9
j = 10, i=6308506

Yup, it's that solitary "$" all alone in the middle of nowhere.
it only took me about an hour and a half to spot - probably because
I was looking in entirely the wrong place as the real-life code had
a large block of comment lines between the "$" and "$i = 0;"

All I can say is aaaaaaaaaaaaaaaaaah!

Teo

unread,
Mar 11, 2010, 8:14:48 AM3/11/10
to
Dear Pete,

Following simple good style guidelines would have spared you a lot of
time:

use warnings;
use strict;

and then it produces:

Global symbol "$i" requires explicit package name at test.pl line 8.
Global symbol "$j" requires explicit package name at test.pl line 9.
Global symbol "$j" requires explicit package name at test.pl line 9.
Global symbol "$j" requires explicit package name at test.pl line 9.
Global symbol "$j" requires explicit package name at test.pl line
10.
Global symbol "$i" requires explicit package name at test.pl line
11.
Global symbol "$j" requires explicit package name at test.pl line
14.
Global symbol "$i" requires explicit package name at test.pl line
14.
Execution of test.pl aborted due to compilation errors.

Fixing the warnings with

my $i;

then causes the error to be discovered:

Scalar found where operator expected at test.pl line 8, near "$


# set up a counter

my $i"
(Missing operator before $i?)
Global symbol "$my" requires explicit package name at test.pl line
8.
syntax error at test.pl line 8, near "$

in any case, if I'm not wrong the program was interpreted as

$$i = 0

And BTW running the script as root is not the best idea :-)

Cheers,

Matteo

ace

unread,
Mar 11, 2010, 8:19:26 AM3/11/10
to
pete wrote:
> j = 7
> j = 8
> j = 9
> j = 10, i=6308506
>
> Yup, it's that solitary "$" all alone in the middle of nowhere.
> it only took me about an hour and a half to spot - probably because
> I was looking in entirely the wrong place as the real-life code had
> a large block of comment lines between the "$" and "$i = 0;"

It's your own fault actually. Put use strict; on top of your program and
try to reproduce misbehavior.


Frank Seitz

unread,
Mar 11, 2010, 8:41:01 AM3/11/10
to
pete wrote:
>
> $
>
> # set up a counter
> $i = 0;

$$i = 0;

This statement creates a scalar reference and assigns it to $i.
This mechanism is called autovivification.
A reference is basically an integer which you can increment:

$$i = 0;
print "$i\n";
$i++;
print "$i\n";
__END__
SCALAR(0x94a3168)
155857257

Frank
--
Dipl.-Inform. Frank Seitz
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Blog: http://www.fseitz.de/blog
XING-Profil: http://www.xing.com/profile/Frank_Seitz2

Ben Morrow

unread,
Mar 11, 2010, 8:58:33 AM3/11/10
to

Quoth Frank Seitz <devnu...@web.de>:

> pete wrote:
> >
> > $
> >
> > # set up a counter
> > $i = 0;
>
> $$i = 0;
>
> This statement creates a scalar reference and assigns it to $i.
> This mechanism is called autovivification.
> A reference is basically an integer which you can increment:

No. A reference can be numified, and will be if you apply a numeric
operator like ++ to it. The result is not a reference, so you can't use
this to go grubbing around in arbitrary bits of memory. (You can use
unpack "P", of course, not to mention more than a few XS modules like
B::Generate.)

Ben

pete

unread,
Mar 11, 2010, 9:04:50 AM3/11/10
to

Not practical - it's not my original code, just my original bug :-(

pete

unread,
Mar 11, 2010, 9:16:30 AM3/11/10
to
On Thu, 11 Mar 2010 14:41:01 +0100, Frank Seitz wrote:
> pete wrote:
>>
>> $
>>
>> # set up a counter
>> $i = 0;
>
> $$i = 0;
>
> This statement creates a scalar reference and assigns it to $i.
> This mechanism is called autovivification.
> A reference is basically an integer which you can increment:
>
> $$i = 0;
> print "$i\n";
> $i++;
> print "$i\n";
> __END__
> SCALAR(0x94a3168)
> 155857257
>
> Frank

What surprised me was that perl didn't see the $<extraneous stuff+whitespace># ...
and try to calculate the size of an array named by the comment, thus:

$# set ...
$i = 0;

which would at least have spat out a syntax error

Frank Seitz

unread,
Mar 11, 2010, 10:17:12 AM3/11/10
to
Ben Morrow wrote:
> Quoth Frank Seitz <devnu...@web.de>:
>> pete wrote:
>>> $
>>>
>>> # set up a counter
>>> $i = 0;
>>
>> $$i = 0;
>>
>> This statement creates a scalar reference and assigns it to $i.
>> This mechanism is called autovivification.
>> A reference is basically an integer which you can increment:
>
> No. A reference can be numified, and will be if you apply a numeric
> operator like ++ to it.

Yes, this is what I meant. The conversion makes sense because
a reference is basically a memory address (plus type),
and a memory address is an integer.

> The result is not a reference, so you can't use
> this to go grubbing around in arbitrary bits of memory.

I did not say that I can do pointer arithmetic on the result.
We talk about Perl, not C :)

Frank Seitz

unread,
Mar 11, 2010, 10:19:08 AM3/11/10
to
pete wrote:
> On Thu, 11 Mar 2010 14:41:01 +0100, Frank Seitz wrote:
>>
>> $$i = 0;
>> print "$i\n";
>> $i++;
>> print "$i\n";
>> __END__
>> SCALAR(0x94a3168)
>> 155857257
>
> What surprised me was that perl didn't see the $<extraneous stuff+whitespace># ...
> and try to calculate the size of an array named by the comment, thus:
>
> $# set ...
> $i = 0;
>
> which would at least have spat out a syntax error

"# set ..." is a comment and is ignored by Perl.
The rest is syntactically ok, because Perl allows whitespace
between the dereference operator $ and the variable $i.

Tad McClellan

unread,
Mar 11, 2010, 10:50:10 AM3/11/10
to
Frank Seitz <devnu...@web.de> wrote:
> pete wrote:
>> On Thu, 11 Mar 2010 14:41:01 +0100, Frank Seitz wrote:
>>>
>>> $$i = 0;
>>> print "$i\n";
>>> $i++;
>>> print "$i\n";
>>> __END__
>>> SCALAR(0x94a3168)
>>> 155857257
>>
>> What surprised me was that perl didn't see
>> the $<extraneous stuff+whitespace># ...
>> and try to calculate the size of an array named by the comment, thus:
>>
>> $# set ...
>> $i = 0;
>>
>> which would at least have spat out a syntax error
>
> "# set ..." is a comment and is ignored by Perl.


You miss pete's point, which was that the "#" was part of "$#...".

"$#set" is the last index of the @set array.

"$# set" is a syntax error.

> The rest is syntactically ok, because Perl allows whitespace
> between the dereference operator $ and the variable $i.


But it does not allow whitespace between the $# and the array name.

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

my @set = qw(one two);

#print $#set, "\n"; # works fine
print $# set, "\n"; # syntax error
---------------------------


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.

s...@netherlands.com

unread,
Mar 11, 2010, 11:02:20 AM3/11/10
to
On Thu, 11 Mar 2010 14:41:01 +0100, Frank Seitz <devnu...@web.de> wrote:

>pete wrote:
>>
>> $
>>
>> # set up a counter
>> $i = 0;
>
>$$i = 0;
>
>This statement creates a scalar reference and assigns it to $i.
>This mechanism is called autovivification.

But, a scalar dereference can't be declared as in:
my $$i = 0;

So, from a declaration standpoint, this
$$i = 0
is actually this
my $i = \0;
a reference to a read-only constant.

>A reference is basically an integer which you can increment:

A reference is a pseudo pointer to other data (of any type).
The reference count increments as below.

$$i = \6;
print "$i\n";
print "$$i\n";
print "$$$i\n";

print "\n";

my $B = \\\\9;
print "$B\n";
print "$$B\n";
print "$$$B\n";
print "$$$$B\n";
print "$$$$$B\n";
__END__

REF(0x22ab94)
SCALAR(0x22ac44)
6

REF(0x182a9bc)
REF(0x182a99c)
REF(0x182a98c)
SCALAR(0x182a92c)
9

-sln

Frank Seitz

unread,
Mar 11, 2010, 11:07:37 AM3/11/10
to
Tad McClellan wrote:
> Frank Seitz <devnu...@web.de> wrote:
>> pete wrote:
>>>
>>> What surprised me was that perl didn't see
>>> the $<extraneous stuff+whitespace># ...
>>> and try to calculate the size of an array named by the comment, thus:
>>>
>>> $# set ...
>>> $i = 0;
>>>
>>> which would at least have spat out a syntax error
>>
>> "# set ..." is a comment and is ignored by Perl.
>
> You miss pete's point, which was that the "#" was part of "$#...".
>
> "$#set" is the last index of the @set array.
>
> "$# set" is a syntax error.

I talked about the original code. In that code is whitespace
between the $ and the #, i.e. # starts a comment.

jl_...@hotmail.com

unread,
Mar 11, 2010, 11:48:34 AM3/11/10
to

> On Thu, 11 Mar 2010 14:19:26 +0100, ace wrote:
>
> > It's your own fault actually. Put use strict; on top of your program and
> > try to reproduce misbehavior.


On Mar 11, 7:04 am, pete <no-...@unknown.com> wrote:
>
> Not practical - it's not my original code, just my original bug :-(


I once inherited several Perl scripts with about one thousand lines
of code in each one. Unfortunately, none of those scripts had "use
strict" and "use warnings" in them.

Originally, I decided it was not practical to add "use strict" and
"use warnings" to the top of the scripts (although I did include them
in the blocks I added). Eventually, maintaining the scripts became
such a huge hassle that I "bit the bullet" and added "use strict" and
"use warnings" to the top of the scripts (and modified the code enough
to comply).

It wasn't easy adding "use strict" and "use warnings" to the files,
but now maintaining the scripts is about ten times easier.

So I recommend adding "use strict" and "use warnings" to the script
you're maintaining, even if it takes you several hours to do so. But
if you can't do that, I still recommend adding them in new blocks you
write (like inside loops, subroutines, and if-blocks). That's not
normally done, but I find it's much better than just never using
"strict" and "warnings" altogether.

-- Jean-Luc

Uri Guttman

unread,
Mar 11, 2010, 1:35:48 PM3/11/10
to
>>>>> "FS" == Frank Seitz <devnu...@web.de> writes:

FS> Yes, this is what I meant. The conversion makes sense because
FS> a reference is basically a memory address (plus type),
FS> and a memory address is an integer.

to be clear, a ref will return a number (the address) in a numeric
context or the TYPE(0xfdddd) style in a string context. it is not a
number but a multivalued thing that returns different things in
different contexts. it is a ref, number AND string all in the same
scalar if you want to see it that way. but once you modify it with ++ it
becomes only a number thereafter.

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------

Glenn Jackman

unread,
Mar 11, 2010, 1:45:03 PM3/11/10
to
At 2010-03-11 11:07AM, "Frank Seitz" wrote:
> Tad McClellan wrote:
> > Frank Seitz <devnu...@web.de> wrote:
> >> pete wrote:
> >>>
> >>> What surprised me was that perl didn't see
> >>> the $<extraneous stuff+whitespace># ...
> >>> and try to calculate the size of an array named by the comment, thus:
> >>>
> >>> $# set ...
> >>> $i = 0;
> >>>
> >>> which would at least have spat out a syntax error
> >>
> >> "# set ..." is a comment and is ignored by Perl.
> >
> > You miss pete's point, which was that the "#" was part of "$#...".
> >
> > "$#set" is the last index of the @set array.
> >
> > "$# set" is a syntax error.
>
> I talked about the original code. In that code is whitespace
> between the $ and the #, i.e. # starts a comment.

We can ask perl what it sees:

perl -MO=Deparse -e '
$
# a comment
$i = 0;
print $i;
'

which gives

$$i = 0;
print $i;
-e syntax OK


--
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous

Frank Seitz

unread,
Mar 11, 2010, 2:02:44 PM3/11/10
to
Uri Guttman wrote:
>>>>>> "FS" == Frank Seitz <devnu...@web.de> writes:
>
> FS> Yes, this is what I meant. The conversion makes sense because
> FS> a reference is basically a memory address (plus type),
> FS> and a memory address is an integer.
>
> to be clear, a ref will return a number (the address) in a numeric
> context or the TYPE(0xfdddd) style in a string context. it is not a
> number but a multivalued thing that returns different things in
> different contexts. it is a ref, number AND string all in the same
> scalar if you want to see it that way. but once you modify it with ++ it
> becomes only a number thereafter.

Very good explanation, except that I would not say that
a reference "returns" something, because it is a (passive) data structure.

Ben Morrow

unread,
Mar 11, 2010, 2:14:09 PM3/11/10
to

Quoth Frank Seitz <devnu...@web.de>:

> Uri Guttman wrote:
> >>>>>> "FS" == Frank Seitz <devnu...@web.de> writes:
> >
> > FS> Yes, this is what I meant. The conversion makes sense because
> > FS> a reference is basically a memory address (plus type),
> > FS> and a memory address is an integer.
> >
> > to be clear, a ref will return a number (the address) in a numeric
> > context or the TYPE(0xfdddd) style in a string context. it is not a
> > number but a multivalued thing that returns different things in
> > different contexts. it is a ref, number AND string all in the same
> > scalar if you want to see it that way. but once you modify it with ++ it
> > becomes only a number thereafter.
>
> Very good explanation, except that I would not say that
> a reference "returns" something, because it is a (passive) data structure.

There's no such thing in Perl. Evaluating a ref in numeric context
numifies it. It's the same as

float a;
int b = 3;
a = b;

in C, which is actually an implicit function call (though Perl caches
the result, which C doesn't).

Ben

Uri Guttman

unread,
Mar 11, 2010, 2:18:57 PM3/11/10
to
>>>>> "FS" == Frank Seitz <devnu...@web.de> writes:

FS> Uri Guttman wrote:
>>>>>>> "FS" == Frank Seitz <devnu...@web.de> writes:
>>
FS> Yes, this is what I meant. The conversion makes sense because
FS> a reference is basically a memory address (plus type),
FS> and a memory address is an integer.
>>
>> to be clear, a ref will return a number (the address) in a numeric
>> context or the TYPE(0xfdddd) style in a string context. it is not a
>> number but a multivalued thing that returns different things in
>> different contexts. it is a ref, number AND string all in the same
>> scalar if you want to see it that way. but once you modify it with ++ it
>> becomes only a number thereafter.

FS> Very good explanation, except that I would not say that
FS> a reference "returns" something, because it is a (passive) data structure.

hard to find a better word for what a value is in different
contexts. returns seems to work even though it isn't a sub. you can say
the same for a sub that checks wantarray or other things that 'return'
different values in different contexts (e.g. arrays). how would you say
this?

arrays return their size in scalar context and a list of their elements
in list context.

Willem

unread,
Mar 11, 2010, 2:28:03 PM3/11/10
to
Ben Morrow wrote:
) There's no such thing in Perl. Evaluating a ref in numeric context
) numifies it. It's the same as
)
) float a;
) int b = 3;
) a = b;
)
) in C, which is actually an implicit function call (though Perl caches
) the result, which C doesn't).

How do you know it doesn't ? The optimizer is allowed to do
anything it pleases as long as the end effect is the same.
Caching results of function calls that are known not to have
side effects is one very common optimization.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

Sherm Pendley

unread,
Mar 11, 2010, 3:07:17 PM3/11/10
to
pete <no-...@unknown.com> writes:

So, spending an hour and a half chasing down a bug that Perl could have
found for you in less than a second *is* practical?

I think we define that word differently...

sherm--

Steve C

unread,
Mar 11, 2010, 3:36:16 PM3/11/10
to

Not a very good excuse. You don't even have to change the code:

perl pete


j = 0
j = 1
j = 2
j = 3
j = 4
j = 5
j = 6

j = 7
j = 8
j = 9

j = 10, i=147926066

perl -w -Mstrict pete
Global symbol "$i" requires explicit package name at pete line 4.
Global symbol "$j" requires explicit package name at pete line 6.
Global symbol "$j" requires explicit package name at pete line 6.
Global symbol "$j" requires explicit package name at pete line 6.
Global symbol "$j" requires explicit package name at pete line 7.
Global symbol "$i" requires explicit package name at pete line 8.
Global symbol "$j" requires explicit package name at pete line 10.
Global symbol "$i" requires explicit package name at pete line 10.
Execution of pete aborted due to compilation errors.

Ben Morrow

unread,
Mar 11, 2010, 3:54:32 PM3/11/10
to

Quoth pete <no-...@unknown.com>:

> On Thu, 11 Mar 2010 14:19:26 +0100, ace wrote:
> >
> > It's your own fault actually. Put use strict; on top of your program and
> > try to reproduce misbehavior.

Strict wouldn't have helped in this case if the variable was declared
already but happened to contain undef:

use strict;

my $x;

...

$
#comment
$x = 1;

The only solution to this sort of problem is to keep your code in source
control, and make small commits. That way, when you break something you
can just 'git diff' or whatever and clearly see what you've changed
since last time it worked.

> Not practical - it's not my original code, just my original bug :-(

It's really not that difficult to do a minimal job. Add 'use strict;',
then keep adding 'my $foo' or 'our $foo' at the top of the file until it
stops complaining about undeclared variables. Anything nasty like
symrefs can be wrapped in an appropriate 'no strict' block.

The result won't be *good* code, but it'll be better than what you had
before and it'll stop you introducing new bugs without meaning to. You
can get round to fixing up the scoping of each piece of code as you come
to it.

Ben

Ilya Zakharevich

unread,
Mar 11, 2010, 4:13:28 PM3/11/10
to
On 2010-03-11, Glenn Jackman <gle...@ncf.ca> wrote:
>> >>> What surprised me was that perl didn't see
>> >>> the $<extraneous stuff+whitespace># ...
>> >>> and try to calculate the size of an array named by the comment, thus:
>> >>>
>> >>> $# set ...
>> >>> $i = 0;

I agree with the surprise...

>> >>> which would at least have spat out a syntax error
>> >>
>> >> "# set ..." is a comment and is ignored by Perl.
>> >
>> > You miss pete's point, which was that the "#" was part of "$#...".
>> >
>> > "$#set" is the last index of the @set array.
>> >
>> > "$# set" is a syntax error.
>>
>> I talked about the original code. In that code is whitespace

^^^^^^^^^^

No. I do not see whitespace there. What I see is "whitespace
interspersed with comments"; this is a different syntaxical element.

>> between the $ and the #, i.e. # starts a comment.

^^^^^^^^^^^^^^^^^^

How does one know? One cannot...

> We can ask perl what it sees:
>
> perl -MO=Deparse -e '
> $
> # a comment
> $i = 0;
> print $i;
> '
>
> which gives
>
> $$i = 0;
> print $i;
> -e syntax OK

You can ask a particular COMPILE of a particular PORT of a particular
VERSION of perl. Given that the observed behaviour is obviously a
bug, you cannot expect that any other guy would reproduce anything
similar... Experimentation has very little value as a path to a
definitive answer.

The only recourse is looking for documentation, but as we all know,
Perl is practically undocumented...

===

Let me sum up: IMO, the bug is in Perl, and not in the script. The
particular construct should not allow interspersed comments.

Hope this helps,
Ilya

sreservoir

unread,
Mar 11, 2010, 4:30:29 PM3/11/10
to

The particular construct really shouldn't allow all sorts of things it
does.

--

"Six by nine. Forty two."
"That's it. That's all there is."
"I always thought something was fundamentally wrong with the universe"

Kyle T. Jones

unread,
Mar 11, 2010, 4:51:37 PM3/11/10
to
jl_...@hotmail.com wrote:

> It wasn't easy adding "use strict" and "use warnings" to the files,
> but now maintaining the scripts is about ten times easier.
>

Why wasn't it easy? Surely you didn't go through and do it manually?
Uhhh, is this that "irony" thing my friends are always going on about?

Cheers.

pete

unread,
Mar 11, 2010, 5:39:26 PM3/11/10
to
Nooo, we define the word the asme. The difference is when you add something
to a few hundred lines of old Perl and then have to spend the rest of the
day nailing each particular non-strict complaint in turn. Then hoping I
don't break something else along the way. Then retesting all the stuff I've
changed instead of just testing the stuff I've added. It could easily turn
a half-day job into a week of work - if done properly, on hourly rates :-)

Kyle T. Jones

unread,
Mar 11, 2010, 6:17:07 PM3/11/10
to
I guess instead of a snark, I could have offered this (it's ugly,
there's undoubtedly an easier way to do it, I invite criticism, but I'm
95% it'll work just fine):

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

sub appendtotop{
my ($olddir, $newdir, $filename)=@_;
my $oldfile=$olddir.$filename;
my $newfile=$newdir.$filename;
open(OLDPERL, $oldfile) || die "cannot open file $oldfile";
open(NEWPERL, ">$newfile")|| die "cannot open file $newfile";
my @contents=<OLDPERL>;
my ($isstrict, $iswarned)=(0,0);

#this looks kind of odd because I'm only checking the first ten
#lines to make sure we don't have duplicate use whatevers
#but it's more because you mentioned that you were dropping
#use strict and use warnings in blocks later on in the code

for (my $i=0; $i<10; $i++){
if($contents[$i]){
$isstrict=1 if($contents[$i]=~/use strict;/);
$iswarned=1 if($contents[$i]=~/use warnings;/);
}
}
my @appendmaterial;
$appendmaterial[0]="use strict;\n" unless($isstrict==1);
$appendmaterial[1]="use warnings;\n" unless($iswarned==1);
print NEWPERL @appendmaterial;
print NEWPERL @contents;
return;
}


my $currentperlscripts='/var/www/cgi-bin/';
my $newdirectory='/var/www/new-cgi-bin/';
opendir(OLD,$currentperlscripts) || die "Cannot opendir
$currentperlscripts: $!";
my @files=readdir(OLD);
foreach (@files){
if($_=~/\.pl/){
appendtotop($currentperlscripts, $newdirectory, $_);
}
}

Peter J. Holzer

unread,
Mar 11, 2010, 6:25:12 PM3/11/10
to

There is no implicit function call here. Did you mean an implicit cast?

> (though Perl caches the result, which C doesn't).

Well, the result is stored in a. So it is "cached" in some sense.
And the compiler is of course free to cache the value of any expression
somewhere in a temporary variable if it thinks it can reuse it. So in some
code like:

x = a + b * c + d;
y = a + b * c;

a C compiler probably will "cache" the result of "a + b * c", while the
perl compiler won't.

hp

Ben Morrow

unread,
Mar 11, 2010, 7:01:28 PM3/11/10
to

Quoth "Peter J. Holzer" <hjp-u...@hjp.at>:

> On 2010-03-11 19:14, Ben Morrow <b...@morrow.me.uk> wrote:
> >
> > There's no such thing in Perl. Evaluating a ref in numeric context
> > numifies it. It's the same as
> >
> > float a;
> > int b = 3;
> > a = b;
> >
> > in C, which is actually an implicit function call
>
> There is no implicit function call here. Did you mean an implicit cast?

I phrased that badly: there is no C function call. But there is an
operation more complicated than simple assignment, such as might result
from the inlining of a function that does the conversion.

I was avoiding the term 'cast' because it means two different things in
C. Sometimes it means an actual conversion from one representation to
another, sometimes it means simply reinterpreting the existing bits as a
different type (casts between pointers to compatible structures, for
instance).

> > (though Perl caches the result, which C doesn't).
>
> Well, the result is stored in a. So it is "cached" in some sense.
> And the compiler is of course free to cache the value of any expression
> somewhere in a temporary variable if it thinks it can reuse it. So in some
> code like:
>
> x = a + b * c + d;
> y = a + b * c;
>
> a C compiler probably will "cache" the result of "a + b * c", while the
> perl compiler won't.

That's true, of course. OTOH, if you have

void bar(int x)
{
float f = x;
}

void foo()
{
int a = 1;
float b = a;
bar(a);
}

it won't, unless it can inline bar to assist the optimization, whereas
perl would.

Ben

Peter J. Holzer

unread,
Mar 11, 2010, 7:07:32 PM3/11/10
to
On 2010-03-11 23:17, Kyle T. Jones <KBf...@realdomain.net> wrote:
> I guess instead of a snark, I could have offered this (it's ugly,
> there's undoubtedly an easier way to do it, I invite criticism, but I'm
> 95% it'll work just fine):
>
[script snipped]

I seem to be missing the part of the script which fixes all the errors
and warnings ...

hp

Frank Seitz

unread,
Mar 12, 2010, 4:32:18 AM3/12/10
to
Ben Morrow wrote:
> Quoth Frank Seitz <devnu...@web.de>:
>> Uri Guttman wrote:
>>>
>>> to be clear, a ref will return a number (the address) in a numeric
>>> context or the TYPE(0xfdddd) style in a string context. it is not a
>>> number but a multivalued thing that returns different things in
>>> different contexts. it is a ref, number AND string all in the same
>>> scalar if you want to see it that way. but once you modify it with ++ it
>>> becomes only a number thereafter.
>>
>> Very good explanation, except that I would not say that
>> a reference "returns" something, because it is a (passive) data structure.
>
> There's no such thing in Perl.

Hm. Perl has no data structures?

> Evaluating a ref in numeric context numifies it.

Yes. But it is perl that interprets and converts the
the scalar (= data structure), not the scalar itself.

> It's the same as
>
> float a;
> int b = 3;
> a = b;
>
> in C, which is actually an implicit function call (though Perl caches
> the result, which C doesn't).

Would you say about line 3: b "returns" a float?

Frank Seitz

unread,
Mar 12, 2010, 4:35:54 AM3/12/10
to
Uri Guttman wrote:
>>>>>> "FS" == Frank Seitz <devnu...@web.de> writes:
>
> FS> Very good explanation, except that I would not say that
> FS> a reference "returns" something, because it is a (passive) data structure.
>
> hard to find a better word for what a value is in different
> contexts. returns seems to work even though it isn't a sub. you can say
> the same for a sub that checks wantarray or other things that 'return'
> different values in different contexts (e.g. arrays). how would you say
> this?

I would say, the reference is "evaluated" or "interpreted"
depending on the context.

> arrays return their size in scalar context and a list of their elements
> in list context.

Paraphrase: Arrays evaluate to their size in scalar context and to a list
of their elements in list context. (?)

Permostat

unread,
Mar 12, 2010, 8:38:30 AM3/12/10
to
On Mar 11, 7:03 am, pete <no-...@unknown.com> wrote:
> I was fixing a problem that "just appeared" in some otherwise working
> code. There were no syntax errors and the program ran fine - it's just
> that the result went from being correct to being uttterly and completely
> wrong. A bit of lateral thinking and investigation solved the problem.
> However, for your entertainment and education, here's a cut down version
> that exhibts the same effect:

>
> $
>
> # set up a counter
> $i = 0;
>
> for($j = 0; $j < 10; $j++) {
>   print "j = $j\n";
>   $i++;}
>
> print "j = $j, i=$i\n";
>
> which, when run produces:
>
> root: perl bug.pl

> j = 0
> j = 1
> j = 2
> j = 3
> j = 4
> j = 5
> j = 6
> j = 7
> j = 8
> j = 9
> j = 10, i=6308506
>
> Yup, it's that solitary "$" all alone in the middle of nowhere.
> it only took me about an hour and a half to spot - probably because
> I was looking in entirely the wrong place as the real-life code had
> a large block of comment lines between the "$" and "$i = 0;"
>
> All I can say is aaaaaaaaaaaaaaaaaah!

Blast it with piss.

Herm=

Kyle T. Jones

unread,
Mar 12, 2010, 11:46:18 AM3/12/10
to

So add in a section that splits the script into subs and main then
parses each for the first instance of declared variables, and append my
to the front of each. That's likely to be a huge percentage of the
errors you'll hit adding in use strict to scripts authored by folks that
don't use, well, use strict.

You know what though - I did think he had said he had "thousands of
scripts" - but what he said was "several scripts of a thousand lines of
code". So, that changes things.

Tell you what, though - you go and create something that "fixes all the
errors and warnings" for any perl script (or any language for that
matter). You'll be rich, @#$%^.

Cheers.

Peter J. Holzer

unread,
Mar 15, 2010, 3:21:15 PM3/15/10
to
On 2010-03-12 00:01, Ben Morrow <b...@morrow.me.uk> wrote:
>
> Quoth "Peter J. Holzer" <hjp-u...@hjp.at>:
>> On 2010-03-11 19:14, Ben Morrow <b...@morrow.me.uk> wrote:
>> >
>> > There's no such thing in Perl. Evaluating a ref in numeric context
>> > numifies it. It's the same as
>> >
>> > float a;
>> > int b = 3;
>> > a = b;
>> >
>> > in C, which is actually an implicit function call
>>
>> There is no implicit function call here. Did you mean an implicit cast?
>
> I phrased that badly: there is no C function call. But there is an
> operation more complicated than simple assignment, such as might result
> from the inlining of a function that does the conversion.

The operation has about the same order of complexity as other C
operators. You wouldn't say that "+" is actually an implicit function call,
would you? Even though for some data types on some architectures an
addition is actually implemented as a function (maybe not even inlined).


> I was avoiding the term 'cast' because it means two different things in
> C. Sometimes it means an actual conversion from one representation to
> another, sometimes it means simply reinterpreting the existing bits as a
> different type (casts between pointers to compatible structures, for
> instance).

Conceptionally it is always a conversion. However, some conversions
happen to be noops. For example, the conversion int -> unsigned int is
arithmetically defined in the standard: For a nonnegative int i,
(unsigned)i is i, for a negative int i, (unsigned)i is i + UINT_MAX + 1.
If you happen to use two's complement representation (all modern
architectures, AFAIK) of signed ints, that's a noop, if you use
sign-magnitude or one's complement, you need to fiddle some bits.
Similarly for pointers: Theoretically pointers to different types could
be different at the bit level, but I don't know any modern architecture
where they are - so casts between pointers are always a noop in
practice (I also remember the quote "all struct pointers smell the
same", but I'm not sure whether that means they have to be the same at
the bit level - it's been too long since I participated in comp.std.c).


>> > (though Perl caches the result, which C doesn't).
>>
>> Well, the result is stored in a. So it is "cached" in some sense.
>> And the compiler is of course free to cache the value of any expression
>> somewhere in a temporary variable if it thinks it can reuse it. So in some
>> code like:
>>
>> x = a + b * c + d;
>> y = a + b * c;
>>
>> a C compiler probably will "cache" the result of "a + b * c", while the
>> perl compiler won't.
>
> That's true, of course. OTOH, if you have
>
> void bar(int x)
> {
> float f = x;
> }
>
> void foo()
> {
> int a = 1;
> float b = a;
> bar(a);
> }
>
> it won't, unless it can inline bar to assist the optimization, whereas
> perl would.

True. OTOH, if the C compiler can inline function calls, it will
probably also optimize away foo() completely ;-).

hp

Peter J. Holzer

unread,
Mar 15, 2010, 3:36:32 PM3/15/10
to
On 2010-03-12 16:46, Kyle T. Jones <KBf...@realdomain.net> wrote:
> Peter J. Holzer wrote:
>> On 2010-03-11 23:17, Kyle T. Jones <KBf...@realdomain.net> wrote:
>>> I guess instead of a snark, I could have offered this (it's ugly,
>>> there's undoubtedly an easier way to do it, I invite criticism, but I'm
>>> 95% it'll work just fine):
>>>
>> [script snipped]
>>
>> I seem to be missing the part of the script which fixes all the errors
>> and warnings ...
>
> So add in a section that splits the script into subs and main then
> parses each for the first instance of declared variables, and append my
> to the front of each. That's likely to be a huge percentage of the
> errors you'll hit adding in use strict to scripts authored by folks that
> don't use, well, use strict.
>
> You know what though - I did think he had said he had "thousands of
> scripts" - but what he said was "several scripts of a thousand lines of
> code". So, that changes things.
>
> Tell you what, though - you go and create something that "fixes all the
> errors and warnings" for any perl script (or any language for that
> matter). You'll be rich, @#$%^.

Well, that was sort of my point. Just mechanically adding a line "use
strict;" is easy, but that almost certainly isn't what keeps the OP from
doing it. Wading through the plethora of warnings and errors and
deciding how to fix them is the real work and that cannot be easily
automated. Automatically generating my() or our() declarations isn't
quite trivial due to the irregular syntax of Perl but should be possible
- but I think the danger of covering up or creating bugs is greater than
the benefit.

I'd do it like this:

When you need to change anything in a script the very first time, you
have to spend some time anyway to read and understand it. So this is the
perfect time to add "use warnings; use strict" an fix all the resulting
errors and warnings as you go. (This is also an advantage of "use
warnings" over "-w" - it affects only the source file, not any used
modules, so you can add it one file at a time)

hp

Kyle T. Jones

unread,
Mar 17, 2010, 1:01:37 PM3/17/10
to
Peter J. Holzer wrote:
> On 2010-03-12 16:46, Kyle T. Jones <KBf...@realdomain.net> wrote:
>> Peter J. Holzer wrote:
>>> On 2010-03-11 23:17, Kyle T. Jones <KBf...@realdomain.net> wrote:
>>>> I guess instead of a snark, I could have offered this (it's ugly,
>>>> there's undoubtedly an easier way to do it, I invite criticism, but I'm
>>>> 95% it'll work just fine):
>>>>
>>> [script snipped]
>>>
>>> I seem to be missing the part of the script which fixes all the errors
>>> and warnings ...
>> So add in a section that splits the script into subs and main then
>> parses each for the first instance of declared variables, and append my
>> to the front of each. That's likely to be a huge percentage of the
>> errors you'll hit adding in use strict to scripts authored by folks that
>> don't use, well, use strict.
>>
>> You know what though - I did think he had said he had "thousands of
>> scripts" - but what he said was "several scripts of a thousand lines of
>> code". So, that changes things.
>>
>> Tell you what, though - you go and create something that "fixes all the
>> errors and warnings" for any perl script (or any language for that
>> matter). You'll be rich, @#$%^.
>
> Well, that was sort of my point. Just mechanically adding a line "use
> strict;" is easy, but that almost certainly isn't what keeps the OP from
> doing it.

Especially given that it was just a couple scripts, what I suggested
wouldn't be helpful at all.

Wading through the plethora of warnings and errors and
> deciding how to fix them is the real work and that cannot be easily
> automated. Automatically generating my() or our() declarations isn't
> quite trivial due to the irregular syntax of Perl but should be possible
> - but I think the danger of covering up or creating bugs is greater than
> the benefit.
>
> I'd do it like this:
>
> When you need to change anything in a script the very first time, you
> have to spend some time anyway to read and understand it. So this is the
> perfect time to add "use warnings; use strict" an fix all the resulting
> errors and warnings as you go. (This is also an advantage of "use
> warnings" over "-w" - it affects only the source file, not any used
> modules, so you can add it one file at a time)
>
> hp
>

Check.

Cheers.

0 new messages