[comp.lang.perl] Bug

worley@compass.uucp (Dale Worley) (11/15/90)

This program dumps core.  I'm sure that it's my problem, but exactly
what am I doing that I'm not allowed to?  (I'm running PL41.)

Dale

Dale Worley		Compass, Inc.			worley@compass.com
--
True, money _can't_ buy happiness, but it isn't happiness I want.  It's money.

#! /usr/local/bin/perl

sub put {
	local(%x);
	local(*array) = *x;
	$save = *x;
	$array{'a'} = 'b';
	print "value saved\n";
}

sub get {
	local(*array) = $save;

	print "fetching...\n";
####### This line causes a segmentation fault:
	$array{'a'};
	print "value retrieved\n";
}

&put();

print "\$save = '$save'\n";

print &get(), "\n";

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (11/16/90)

In article <1990Nov15.003912.26468@uvaarpa.Virginia.EDU> worley@compass.uucp writes:
: This program dumps core.  I'm sure that it's my problem, but exactly
: what am I doing that I'm not allowed to?  (I'm running PL41.)
: 
: Dale
: 
: Dale Worley		Compass, Inc.			worley@compass.com
: --
: True, money _can't_ buy happiness, but it isn't happiness I want.  It's money.
: 
: #! /usr/local/bin/perl
: 
: sub put {
: 	local(%x);
: 	local(*array) = *x;
: 	$save = *x;
: 	$array{'a'} = 'b';
: 	print "value saved\n";
: }
: 
: sub get {
: 	local(*array) = $save;
: 
: 	print "fetching...\n";
: ####### This line causes a segmentation fault:
: 	$array{'a'};
: 	print "value retrieved\n";
: }
: 
: &put();
: 
: print "\$save = '$save'\n";
: 
: print &get(), "\n";

A symbol table entry such as *x merely contains pointers to various
objects called by the name 'x'.

What's happening is that you're making a copy of the symbol table entry
for x while it has a pointer to a local copy of %x.  When you leave the
scope of the local in &put, the local %x is destroyed, and the *x symbol
table entry is restored to having it's global %x array value.  But your
copy of the symbol table entry in $save still has the pointer to the
local array that has been freed.  So naturally, when you try to dereference
that pointer, you blow up.

The solution, of course, will be to put reference counts on things so
they aren't freed till all their references go away.  This has been
planned for some time, but probably won't happen until after 4.0 comes
out.  When it does happen, most of the advice about $&, $1, $2... being
slow will become obsolete, since I'd then be able to make those just
refer into the string that was searched, instead of making a copy of
the string as I do now.  In other words, move to more of a
copy-on-write implementation, hopefully in a topologically transparent
fashion.

On the other hand, there's already a lot of overhead for each string,
and adding a reference count won't help with that.  But memory's getting
cheaper.  I might be able to shoehorn a reference count in on top of
the numeric value by disallowing multiple references on scalars with
a numeric value, but it wouldn't be as clean.  I do occasionally worry
about that.  :-)

If Perl were written in proper C++, it would be a lot easier to understand,
and would run in twice the memory...

Larry

worley@compass.com (Dale Worley) (03/28/91)

I'm running Perl 3.44.  At line 885 in perly.c, there is the following
code:

	    tmpfilename = savestr(specfilename);
	    if (index("/.", *tmpfilename))
		rsfp = fopen(tmpfilename,"r");
	    else {
		ar = stab_array(incstab);
	        for (i = 0; i <= ar->ary_fill; i++) {
		[etc.]

This code is responsible for implementing the 'do' and 'require'
operators, in particular, looking up the correct file using the @INC
array.  The effect of the above 'if' is that if the argument to 'do'
or 'require' *contains* the substring '/.', then the searching in @INC
is suppressed.

This behavior is undocumented in The Book, and its purpose escapes me.
Since the file I'm trying to include is '../../src/ioctl.pl', it
screws me.  What is going on here?

Dale

Dale Worley		Compass, Inc.			worley@compass.com
--
The genius of you Americans is that you never make any clear-cut
stupid moves, only complicated stupid moves that leave us scratching
our heads wondering if we might possibly have missed something.
-- Gamel Abdel Nasser

worley@compass.com (Dale Worley) (03/29/91)

   X-Name: Raymond Chen

   In article <1991Mar27.205437.28251@uvaarpa.Virginia.EDU> you write:
   >	    if (index("/.", *tmpfilename))
   >
   >The effect of the above 'if' is that if the argument to 'do'
   >or 'require' *contains* the substring '/.', then the searching in @INC
   >is suppressed.

   Methinks you are mistaken.  The test in question says `check if the
   first character of tmpfilename is a dot or a slash'.  Observe the
   `*' in front of tmpfilename, and reread the man page for index(3).

Oops.  Much embarrassed.  I should have checked it more carefully.

However, its behavior is still peculiar -- the check should be for
"starts with slash or with dot-slash".  If a name starts with dot-dot,
the user may well want to have it searched for.

Dale

Dale Worley		Compass, Inc.			worley@compass.com
--
Never share a foxhole with anyone braver than yourself.
-- Murphy's Laws of Combat