Skip to content

Pointer ownership with GECreateDevDesc/GEDestroyDevDesc

3 messages · Ritch Melton, Paul Murrell

#
According to the "R Internals" document, for a custom device, I should
create a pDevDesc structure that gets passed to GECreateDevDesc.

..elided...
pDevDesc dev;
/* Allocate and initialize the device driver data */
if (!(dev = (pDevDesc) calloc(1, sizeof(DevDesc)))) return 0;
/* or error() */
/* set up device driver or free ?dev? and error() */
gdd = GEcreateDevDesc(dev); GEaddDevice2(gdd, "dev_name");
...elided...

which indicates to me that the calling code owns the pDevDesc structure and
should be responsible for freeing it.
However, in GEdestroyDevDesc, that particular code calls free(dd->dev),
freeing the pointer.

In my case, I have a device implemented and created in a language that is
using a different allocator. The pDevDesc I pass in is not owned by R and
causes a crash on free with "dev.off()".

I thought I could mitigate the issue, by making a call to the allocator R
is using via an exported R function, such as R_alloc, but I did not see
such a function available to me.

I would like to know if I should be creating the pDevDesc via an imported
alloc routine somehow? or is there a way to prevent this code from freeing
the structure I pass in.

Blue Skies,
Ritch
2 days later
#
I perused the source for RStudio and noticed that they had a similar
problem. I didn't think that the GEDevDesc structure was exported, but
apparently this is a worthwhile workaround to the defect.

void GD_Close(pDevDesc dev)
{
...elided...
      // explicitly free and then null out the dev pointer of the GEDevDesc
      // This is to avoid incompatabilities between the heap we are
compiled with
      // and the heap R is compiled with (we observed this to a problem with
      // 64-bit R)
      std::free(s_pGEDevDesc->dev);
      s_pGEDevDesc->dev = NULL;

      // set GDDevDesc to NULL so we don't reference it again
      s_pGEDevDesc = NULL;
   }
}

I will
On Fri, Sep 19, 2014 at 10:37 AM, Ritch Melton <skyguy94 at gmail.com> wrote:

            

  
  
1 day later
#
This seems like the best solution (free and NULL the dev pointer in 
dev_Close(), BEFORE GEdestroyDevDesc() has a go).

I think this should be safe because dev_Close() and GEdestroyDevDesc() 
are only called in one place (so your free() should always happen before 
GEdestroyDevDesc() and your free() shouldn't happen in any other, 
potentially inappropriate, context).

Paul
On 09/23/14 03:15, Ritch Melton wrote: