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
System Administrator
June 27, 2002 16:24
[ID 20020627.004] For-loop fails to reclaim memory but While-loop OK
Message ID:
This is a bug report for perl from,
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

	- 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

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

<test_program name=show_perl_bug> {{
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') {
} elsif ($case eq 'good') {
} 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))
		last if $count >= 15000;

# This works fine.
sub test_while_loop
	my $count = 0;
	my $feat = first_object();
	while ($feat)
		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]
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:
    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
    cc='gcc', ccflags ='-fno-strict-aliasing -I/wcs/lib -I/usr/local/include',
    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/, 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:

Environment for perl v5.6.1:
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PERL_BADLANG (unset)

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About