I have been trying to track down a memory leak off and on for sometime
now.
If anyone can see what I am doing wrong I would greatly appreciate the
help.

We have embedded a perl interpreter into our C code.  Whenever I call
the
"PerlCallFctn" routine,  I end up with a 4k memory leak.  This may not
seem
like a big leak but this function may get called thousands of time.  I
have deleted section
of code that never gets called.  This was built using perl 5.6.1 .

Thanks for any help.

Bob




/************************************************************************************/

/*  Function:  PerlCallFctn             */
/************************************************************************************/

static int
PerlCallFctn( PerlInterpreter *my_perl, const char *pczFuncName,
     DISPPARAMS *pDispParms, VARIANTARG *ps_Result )
{
 /* Note: The following macros assume that there is a perl interpreter
named
     my_perl in the scope... */

 /*
  * pre_Push_Declare
  */

    dSP ;
    SV *pVal;
 /*
  * declare other vars here
  */

 long iIsOk = 0;

    int iCount;
    int i;

 VariantClear ( ps_Result );



 if(my_perl)
 {
  /*
   * pre_push
   */

  ENTER ;
  SAVETMPS;
  PUSHMARK(SP) ;

  iIsOk = 1;

  if ( pDispParms && pDispParms->cArgs )
  {
   /* push inputs to perl function being called onto perl stack*/
   for( i=0; i < pDispParms->cArgs; ++i )
   {
    VARIANTARG *ps_vArg = &pDispParms->rgvarg[i];
    enum VARENUM eType = (enum VARENUM) V_VT(ps_vArg);

    if ( eType & VT_ARRAY )
    {
     XPUSHs( sv_2mortal(newRV_noinc( PerlCreateCallArray ( my_perl,
ps_vArg, &iIsOk ) ) ) );
    }

   } /* End for */
  }

  if( !iIsOk )
  {
   **** never enters here
   PUTBACK ;
   SPAGAIN ;
   PUTBACK ;
   FREETMPS ;
    LEAVE ;

   return( iIsOk );
  }

  /*
   * post_Push
   */

  /* From code in artical CUJ Jan/2002,A stream class for calling Perl
from C++*/
  sv_setsv(ERRSV, &PL_sv_undef);
  PUTBACK ;

  /*
   * call Perl fctn : do NOT use G_DISCARD which ends up removing any
returned values from the stack
   */

  iCount = call_pv     ( pczFuncName, G_SCALAR | G_EVAL );

  /*
   * post_call
   */

  SPAGAIN ;

  /*
   *  Check error code
   */

  /* From code in artical CUJ Jan/2002,A stream class for calling Perl
from C++*/
  if ( SvTRUE(ERRSV) )
  {
             does not enter here
  }

  else
  {
   /*
    * process returned data from Perl Function call
    */

   if( iCount )
   {
    pVal = POPs;

    iIsOk = PerlProcessReturnValue ( my_perl, pVal, ps_Result );
   }
  }

  /*
   * post_process
   */

  PUTBACK ;
  FREETMPS ;
  LEAVE ;

 }

 return ( iIsOk );
}


/************************************************************************************/

/*  Function:  PerlCreateCallArray           */
/************************************************************************************/

static SV*
PerlCreateCallArray ( PerlInterpreter *my_perl, const VARIANTARG
*ps_InVariant, long *piIsOk )
{
 long  iUbound,
    iLbound,
    i1,
    iIsOk = 1;

 SAFEARRAY  *ps_SafeArray = V_ARRAY(ps_InVariant);
 VARIANTARG *ps_Variants;

 AV     *pPerlArray = newAV();

 SafeArrayGetUBound ( ps_SafeArray, 1, &iUbound );
 SafeArrayGetLBound ( ps_SafeArray, 1, &iLbound );
 SafeArrayAccessData ( ps_SafeArray, (void**)&ps_Variants );

 for ( i1 = iLbound; i1 <= iUbound; ++i1 )
 {
  VARIANTARG    *ps_CurrVariant = &ps_Variants[i1];
  enum VARENUM  eCurrType       = (enum VARENUM) V_VT(ps_CurrVariant);

  if(eCurrType & VT_ARRAY)
  {
   av_push
    ( pPerlArray,
     newRV_noinc
     (
      PerlCreateCallArray
      ( my_perl, ps_CurrVariant, &iIsOk
      )
     )
    );
  }
  else
  {
   switch(eCurrType)
   {
   case VT_EMPTY:
   case VT_NULL:
    av_push( pPerlArray, newSVsv(&PL_sv_undef) );
    break;

   case VT_R8:
    av_push( pPerlArray, newSVnv(V_R8(ps_CurrVariant)) );
    break;

   }
  }

 } /* End for */

 *piIsOk = iIsOk;

 return (SV*) pPerlArray;
}



/
/************************************************************************************/

/*  Function:  PerlProcessReturnValue          */
/************************************************************************************/

static int
PerlProcessReturnValue ( PerlInterpreter *my_perl, SV *pVal, VARIANTARG
*ps_Result )
{
 int iIsOk = 1;
 svtype eValType = (svtype) SvTYPE(pVal);

 VariantClear( ps_Result );

 switch( eValType )
 {

 case SVt_NV:
 case SVt_PVNV:
  if ( SvNOK(pVal) )
  {
   V_VT(ps_Result) = VT_R8;
   V_R8(ps_Result) = SvNV(pVal);
  }
  else
  {
   ***never enters here
  }
  break;

 case SVt_PVAV:
  {
   AV    *pArrayVal = (AV*) pVal;
   long    iLength = av_len ( pArrayVal ),
     i;
   SAFEARRAY  *pSafeArray = NULL;
   SAFEARRAYBOUND dim[1];
   dim[0].lLbound = 0;
   dim[0].cElements = iLength+1;

   pSafeArray = SafeArrayCreate(VT_VARIANT, 1, dim);

   {
    SV     **ppElementValue;

    VARIANTARG s_VariantValue;

    VariantInit ( &s_VariantValue );

    for ( i = 0; i <= iLength; ++i )
    {
     VariantClear ( &s_VariantValue );
     (ppElementValue) = av_fetch( pArrayVal, i, 0 );

     iIsOk = PerlProcessReturnValue ( my_perl, *ppElementValue,
&s_VariantValue );

     if ( iIsOk )
     {
      SafeArrayPutElement( pSafeArray, &i, (void*) &s_VariantValue );
     }
     else
     {
      ****never enter here
      break;
     }
    }

    VariantClear ( &s_VariantValue );

    if ( iIsOk )
    {
     V_VT(ps_Result)    = VT_ARRAY | VT_VARIANT;
     V_ARRAY(ps_Result) = pSafeArray;
    }
    else
    {
     ****never enters here
    }
   }
  }
  break;

 case SVt_RV:

  {
   SV *pDerefVal =  SvRV( pVal );
   iIsOk = PerlProcessReturnValue ( my_perl, pDerefVal, ps_Result );
  }
  break;

 }

 return iIsOk;
}




Reply via email to