Hi Everyone,

I've been staring at this for hours now and I can't work out where I'm leaking memory in a perl XS module I'm working on. Basically, I need to take a tree of C structures:

    typedef struct _SGraph {
        char *name;
        int size;
        Graph list[];
    } * Graph;

with a given head pointer and iterate through the graph and produce Perl hashes which look like { name => "__root__", parent => undef, list = [ { name => "child" }, parent => (ref to parent), list = ... } ]. I've got the algorithm working a number of different ways but each one leaks memory. I'm sending the current implementation along with this post, sorry for the long post, this is the shortest example that demonstrates the issue.

Thanks,
Shaun

SV *RvFromRv_noinc(SV *ptRv)
{
   return(newRV_noinc(SvRV(ptRv)));
}

HV *MakeHash(Graph ptGraph, SV *ptParent)
{
   static HV *ptGraphStash = NULL;
   HV *ptHash;
   SV *ptSubHash;
   AV *ptArray;
   int i;
   SV *ptResult;

   if (ptGraphStash == NULL)
   {
      ptGraphStash = gv_stashpv("OGDL::Graph", 0);
      if (!ptGraphStash)
         ptGraphStash = (HV *) -1;
   }

   ptHash = (HV *) newHV();

   if (!ptParent)
      /* Storing &PL_sv_undef does not work */
      hv_fetch(ptHash, "parent", 6, 1);
   else
      /* Store the reference to our parent */
      hv_store(ptHash, "parent", 6, RvFromRv(ptParent), 0);

   hv_store(ptHash, "name", 4, newSVpv(ptGraph->name, 0), 0);

   ptResult = newRV_noinc((SV *) ptHash);

   ptArray = newAV();
   av_extend(ptArray, ptGraph->size);
   for (i = 0; i < ptGraph->size; i++)
   {
      ptSubHash = MakeHash(ptGraph->nodes[i], ptResult);
      av_push(ptArray, RvFromRv_noinc((SV *) ptSubHash));
   }

   hv_store(ptHash, "list", 4, newRV_noinc((SV *) ptArray), 0);

   if (ptGraphStash && (ptGraphStash != (HV *) -1))
      sv_bless(ptResult, ptGraphStash);

   return(ptResult);
}

MODULE = OGDL::NativeParser      PACKAGE = OGDL::NativeParser

SV *GraphFile(char *sFile)
{
   SV *ptResult = NULL;
...
    ptResult = MakeHash(*ptParser->g, NULL);

    return(ptResult);
}

SV *
load(file)
      char *file
   PREINIT:
      Graph ptGraph = NULL;
   CODE:
      /* Create perl hashes to return */
      RETVAL = GraphFile(file);
   OUTPUT:
      RETVAL





Reply via email to