develooper Front page | perl.perl5.porters | Postings from June 2002

[ID 20020627.004] For-loop fails to reclaim memory but While-loop OK

Thread Next
From:
System Administrator
Date:
June 27, 2002 16:24
Subject:
[ID 20020627.004] For-loop fails to reclaim memory but While-loop OK
Message ID:
E17NiXV-0006QF-00@world.evansville.net
This is a bug report for perl from chkoreff@cinergycom.net,
generated with the help of perlbug 1.33 running under perl v5.6.1.


-----------------------------------------------------------------
[Please enter your report here]

Quick background, bear with me.  I have developed some great object-oriented
database classes that let you iterate concisely with loops like this:

	for (my $cust = Customer->list_by_name($db); $cust; $cust = $cust->next) {
		print "Customer ".$cust->name."\n";
	}

That kind of thing.  Problem is, I found that as I loop through LOTS of
Customer records, the program starts consuming more and more memory until
it eventually dumps core.  To avoid this problem, I have to change the for-loop
into the equivalent while-loop like this:

	my $cust = Customer->list_by_name($db);
	while ($cust) {
		print "Customer ".$cust->name."\n";
		$cust = $cust->next;
	}

According to page 99 of the Camel book, and according to standard C usage,
these two loops are supposed to be equivalent.  However, the for-loop dumps
core and the while-loop does not.

I have included a nice little standalone test program that demonstrates the
problem.  It uses only basic stuff -- no databases or blessed references.
To run the bad for-loop, just type "show_perl_bug bad".  To run the good
while-loop, type "show_perl_bug good".

I have run this program on two different Perl versions for Solaris.  It
failed on both of these versions:

	- This is perl, version 5.004_04 built for sun4-solaris   (FAILS)
	- This is perl, v5.6.1 built for sun4-solaris-perlio      (FAILS)

I ran the program on a Linux machine and IT WORKED FINE!  Here is that
version:

	- This is perl, version 5.005_03 built for i386-linux     (SUCCEEDS!)

Note that my stripped-down test program isn't "realistic" or anything.
Nevertheless, it should work.  To get the core dump, you might have to
bump up the limit of 15000.  Or just run "top" and watch the memory
grow.

OK, that's it.  Here's the test program.  Thanks for your help!

<test_program name=show_perl_bug> {{
#!/bin/perl
use strict;

# Patrick Chkoreff 2002-06-27:   The "show_perl_bug" program.
# Illustrates Perl bug.  You CANNOT use the "for" loop syntax safely in this
# example.  For some reason, Perl does not garbage collect properly.

my $case = $ARGV[0];

if ($case eq 'bad') {
	test_for_loop();
} elsif ($case eq 'good') {
	test_while_loop();
} else {
	print STDERR "Usage:  $0 (good | bad)\n";
}

# This uses up unbounded memory and eventually dumps core.
sub test_for_loop
{
	my $count = 0;
	my $feat;
	for ($feat = first_object(); $feat; $feat = next_object($feat))
	{
		$count++;
		last if $count >= 15000;
	}
}

# This works fine.
sub test_while_loop
{
	my $count = 0;
	my $feat = first_object();
	while ($feat)
	{
		$count++;
		last if $count >= 15000;

		$feat = next_object($feat);
	}
}

sub first_object
{
	return {};
}

sub next_object
{
	my $self = shift;
	my $next = {};
	$self->{next} = $next;
	return $next;
}
</test_program> }}


[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=high
---
Site configuration information for perl v5.6.1:

Configured by hill at Thu Jan 24 05:06:12 CST 2002.

Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration:
  Platform:
    osname=solaris, osvers=2.6, archname=sun4-solaris-perlio
    uname='sunos world 5.6 generic_105181-26 sun4u sparc sunw,ultraax-mp '
    config_args='-Ubincompat5005 -Dprefix=/wcs -Duseperlio -Dusefio -DTWO_POT_OPTIMIZE -Dusethreads -Uuselargefiles'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=define uselargefiles=undef usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
  Compiler:
    cc='gcc', ccflags ='-fno-strict-aliasing -I/wcs/lib -I/usr/local/include',
    optimize='-O',
    cppflags='-fno-strict-aliasing -I/wcs/lib -I/usr/local/include'
    ccversion='', gccversion='2.95.3 20010315 (release)', gccosandvers='solaris2.6'
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=4
    alignbytes=8, usemymalloc=y, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags ='-L/wcs/lib -R/wcs/lib -L/usr/local/lib'
    libpth=/wcs/lib /usr/local/lib /usr/lib /usr/ccs/lib
    libs=-lsfio -lsocket -lnsl -lgdbm -ldb -ldl -lm -lc
    perllibs=-lsfio -lsocket -lnsl -ldl -lm -lc
    libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-fPIC', lddlflags='-G -L/wcs/lib -R/wcs/lib -L/usr/local/lib'

Locally applied patches:
    

---
@INC for perl v5.6.1:
    /wcs/lib/perl5/5.6.1/sun4-solaris-perlio
    /wcs/lib/perl5/5.6.1
    /wcs/lib/perl5/wcs/5.6.1/sun4-solaris-perlio
    /wcs/lib/perl5/wcs/5.6.1
    /wcs/lib/perl5/wcs
    .

---
Environment for perl v5.6.1:
    HOME=/home/chkoreff
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/chkoreff/bin:../bin:/local/bin:/wcs/bin:/local/gnu/bin:/bin:/usr/ucb:/local/etc:/wcs/etc:/usr/etc:/etc:/usr/sbin:/usr/ccs/bin:/usr/ccs/lib:/etc/rc2.d:/wcs/bin/netpbm:/usr/openwin/bin:/wcs/mysql/bin:/wcs/msql2/bin:.
    PERL_BADLANG (unset)
    SHELL=/bin/ksh


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About