[Cc:'ing me appreciated - I will poll the archive, though]

I downloaded ReadDir module from CPAN. I works great, but leaks memory.
I tried to make sense of where the leak takes place, but even with the help
of perl-xs mailing list archives I couldn't spot it.

Could someone tell me off hand what is being done wrong in the following
snippet?

(Confirmed as leaky with perl 5.6.1 and perl 5.0-5-3.)


My current (leaky) try (trying to make a hash instead of an array):
-------------------------------------------------------------------------
/*  <=-*- C -*-=>  */

#include "EXTERN.h"           
#include "perl.h"
#include "XSUB.h"
#include <sys/types.h>   
#include <dirent.h>
#include <stdio.h>

MODULE = ReadDir                PACKAGE = ReadDir

void
readdir_inode(dirname)
     char*    dirname
INIT:
  struct dirent *ent;
  DIR* dir;
  AV *entry, *ret_val;
  HV* hash;
PPCODE:
  dir = opendir(dirname);
  hash = newHV();

  if (dir) {
     while ((ent = readdir(dir))) {
         hv_store_ent(hash, newSVpvf(ent->d_name),
                      newSViv(ent->d_ino), 0);
     }

     closedir(dir);   

     XPUSHs(sv_2mortal(newRV_noinc((SV *) hash)));
  }
------------------------------------------------------------------------

The original ReadDir 0.01 from CPAN (leaks too):
------------------------------------------------------------------------
/*  <=-*- C -*-=>  */

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>

MODULE = ReadDir                PACKAGE = ReadDir               

void
readdir_inode(dirname)
     char*    dirname
INIT:
  struct dirent *ent;
  DIR* dir;
  SV* record[2];
  AV *entry, *ret_val;
PPCODE:
  dir = opendir(dirname);
  if (dir) {
    while ((ent=readdir(dir))) {
      record[0] = newSVpv(ent->d_name, 0);
      record[1] = newSViv((IV)ent->d_ino);
      PUSHs(sv_2mortal(newRV_inc((SV*)av_make(2, record))));
    }
    closedir(dir);
  }
------------------------------------------------------------------------

                                                     
Test program to see if it leaks:                     
-------------------------------------------------------------------------
#!/usr/bin/perl                                      
                                                     
$time = 0;                                           
$calls = 0;                                          
                                                     
use ReadDir qw/ readdir_inode /;                     
                      
sub stats()          
{    
        $calls++;    
        return unless (time() - $time >= 1);
        $time = time();
                      
        my $vmsize;
        open I, "< /proc/self/status" or return 0;   
        while (<I>)                                  
        {                                            
                next unless /^VmSize:\s+(\d+)/;      
                $vmsize = $1;                        
                last;                                       
        }
        close I;                                     
   
        print "$calls calls; memory used: $vmsize\n";                   
}
                                                     

for ($i = 0; $i < 100000; $i++)
{
    stats();                                         
    readdir_inode('/tmp');                           
}
------------------------------------------------------------------------

 
-- v --

[EMAIL PROTECTED]

Reply via email to