[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]