Fix memory leak in R shared_ptr wrappers
Fix leak when a cast up a class inheritance chain is required. Adds implementation of SWIG_ConvertPtrAndOwn for R. Closes #2386
This commit is contained in:
parent
24b0e68391
commit
9e7610f972
4 changed files with 36 additions and 22 deletions
|
|
@ -7,3 +7,7 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
||||||
Version 4.2.0 (in progress)
|
Version 4.2.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2022-10-26: wsfulton
|
||||||
|
[R] #2386 Fix memory leak in R shared_ptr wrappers.
|
||||||
|
Fix leak when a cast up a class inheritance chain is required.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@ testSuite <- function() {
|
||||||
testSuite_verifyCount(2, kret)
|
testSuite_verifyCount(2, kret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# pass by shared_ptr pointer reference
|
||||||
{
|
{
|
||||||
# pass by shared_ptr pointer reference
|
|
||||||
k = Klass("me oh my")
|
k = Klass("me oh my")
|
||||||
kret = smartpointerpointerreftest(k)
|
kret = smartpointerpointerreftest(k)
|
||||||
val = kret$getValue()
|
val = kret$getValue()
|
||||||
|
|
@ -312,8 +312,8 @@ testSuite <- function() {
|
||||||
kret = smartpointertest(k)
|
kret = smartpointertest(k)
|
||||||
val = kret$getValue()
|
val = kret$getValue()
|
||||||
unittest("me oh my smartpointertest-Derived", val)
|
unittest("me oh my smartpointertest-Derived", val)
|
||||||
#testSuite_verifyCount(2, k)
|
testSuite_verifyCount(2, k)
|
||||||
#testSuite_verifyCount(2, kret)
|
testSuite_verifyCount(2, kret)
|
||||||
}
|
}
|
||||||
|
|
||||||
# pass by shared_ptr pointer (mixed)
|
# pass by shared_ptr pointer (mixed)
|
||||||
|
|
@ -322,8 +322,8 @@ testSuite <- function() {
|
||||||
kret = smartpointerpointertest(k)
|
kret = smartpointerpointertest(k)
|
||||||
val = kret$getValue()
|
val = kret$getValue()
|
||||||
unittest("me oh my smartpointerpointertest-Derived", val)
|
unittest("me oh my smartpointerpointertest-Derived", val)
|
||||||
#testSuite_verifyCount(2, k)
|
testSuite_verifyCount(2, k)
|
||||||
#testSuite_verifyCount(2, kret)
|
testSuite_verifyCount(2, kret)
|
||||||
}
|
}
|
||||||
|
|
||||||
# pass by shared_ptr reference (mixed)
|
# pass by shared_ptr reference (mixed)
|
||||||
|
|
@ -332,8 +332,8 @@ testSuite <- function() {
|
||||||
kret = smartpointerreftest(k)
|
kret = smartpointerreftest(k)
|
||||||
val = kret$getValue()
|
val = kret$getValue()
|
||||||
unittest("me oh my smartpointerreftest-Derived", val)
|
unittest("me oh my smartpointerreftest-Derived", val)
|
||||||
#testSuite_verifyCount(2, k)
|
testSuite_verifyCount(2, k)
|
||||||
#testSuite_verifyCount(2, kret)
|
testSuite_verifyCount(2, kret)
|
||||||
}
|
}
|
||||||
|
|
||||||
# pass by shared_ptr pointer reference (mixed)
|
# pass by shared_ptr pointer reference (mixed)
|
||||||
|
|
@ -342,8 +342,8 @@ testSuite <- function() {
|
||||||
kret = smartpointerpointerreftest(k)
|
kret = smartpointerpointerreftest(k)
|
||||||
val = kret$getValue()
|
val = kret$getValue()
|
||||||
unittest("me oh my smartpointerpointerreftest-Derived", val)
|
unittest("me oh my smartpointerpointerreftest-Derived", val)
|
||||||
#testSuite_verifyCount(2, k)
|
testSuite_verifyCount(2, k)
|
||||||
#testSuite_verifyCount(2, kret)
|
testSuite_verifyCount(2, kret)
|
||||||
}
|
}
|
||||||
|
|
||||||
# pass by value (mixed)
|
# pass by value (mixed)
|
||||||
|
|
@ -352,8 +352,8 @@ testSuite <- function() {
|
||||||
kret = valuetest(k)
|
kret = valuetest(k)
|
||||||
val = kret$getValue()
|
val = kret$getValue()
|
||||||
unittest("me oh my valuetest", val) # note slicing
|
unittest("me oh my valuetest", val) # note slicing
|
||||||
#testSuite_verifyCount(1, k)
|
testSuite_verifyCount(1, k)
|
||||||
#testSuite_verifyCount(1, kret)
|
testSuite_verifyCount(1, kret)
|
||||||
}
|
}
|
||||||
|
|
||||||
# pass by pointer (mixed)
|
# pass by pointer (mixed)
|
||||||
|
|
@ -362,8 +362,8 @@ testSuite <- function() {
|
||||||
kret = pointertest(k)
|
kret = pointertest(k)
|
||||||
val = kret$getValue()
|
val = kret$getValue()
|
||||||
unittest("me oh my pointertest-Derived", val)
|
unittest("me oh my pointertest-Derived", val)
|
||||||
#testSuite_verifyCount(1, k)
|
testSuite_verifyCount(1, k)
|
||||||
#testSuite_verifyCount(1, kret)
|
testSuite_verifyCount(1, kret)
|
||||||
}
|
}
|
||||||
|
|
||||||
# pass by ref (mixed)
|
# pass by ref (mixed)
|
||||||
|
|
@ -372,8 +372,8 @@ testSuite <- function() {
|
||||||
kret = reftest(k)
|
kret = reftest(k)
|
||||||
val = kret$getValue()
|
val = kret$getValue()
|
||||||
unittest("me oh my reftest-Derived", val)
|
unittest("me oh my reftest-Derived", val)
|
||||||
#testSuite_verifyCount(1, k)
|
testSuite_verifyCount(1, k)
|
||||||
#testSuite_verifyCount(1, kret)
|
testSuite_verifyCount(1, kret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -420,7 +420,7 @@ testSuite <- function() {
|
||||||
testSuite_verifyCount(1, k)
|
testSuite_verifyCount(1, k)
|
||||||
val = test3rdupcast(k)
|
val = test3rdupcast(k)
|
||||||
unittest("me oh my-3rdDerived", val)
|
unittest("me oh my-3rdDerived", val)
|
||||||
# testSuite_verifyCount(1, k)
|
testSuite_verifyCount(1, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,9 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* for raw pointer */
|
/* for raw pointer */
|
||||||
|
#define SWIG_R_ConvertPtr(obj, pptr, type, flags) SWIG_R_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
|
||||||
#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_R_ConvertPtr(obj, pptr, type, flags)
|
#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_R_ConvertPtr(obj, pptr, type, flags)
|
||||||
#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_R_ConvertPtr(obj, pptr, type, flags)
|
#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_R_ConvertPtrAndOwn(obj, pptr, type, flags, own)
|
||||||
#define SWIG_NewPointerObj(ptr, type, flags) SWIG_R_NewPointerObj(ptr, type, flags)
|
#define SWIG_NewPointerObj(ptr, type, flags) SWIG_R_NewPointerObj(ptr, type, flags)
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -314,9 +315,11 @@ SWIG_R_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
|
||||||
|
|
||||||
/* Convert a pointer value */
|
/* Convert a pointer value */
|
||||||
SWIGRUNTIMEINLINE int
|
SWIGRUNTIMEINLINE int
|
||||||
SWIG_R_ConvertPtr(SEXP obj, void **ptr, swig_type_info *ty, int flags) {
|
SWIG_R_ConvertPtrAndOwn(SEXP obj, void **ptr, swig_type_info *ty, int flags, int *own) {
|
||||||
void *vptr;
|
void *vptr;
|
||||||
if (!obj) return SWIG_ERROR;
|
if (!obj) return SWIG_ERROR;
|
||||||
|
if (own)
|
||||||
|
*own = 0;
|
||||||
if (obj == R_NilValue) {
|
if (obj == R_NilValue) {
|
||||||
if (ptr) *ptr = NULL;
|
if (ptr) *ptr = NULL;
|
||||||
return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK;
|
return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK;
|
||||||
|
|
@ -331,8 +334,15 @@ SWIG_R_ConvertPtr(SEXP obj, void **ptr, swig_type_info *ty, int flags) {
|
||||||
} else {
|
} else {
|
||||||
swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
|
swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
|
||||||
int newmemory = 0;
|
int newmemory = 0;
|
||||||
if (ptr) *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
|
if (ptr) {
|
||||||
assert(!newmemory); /* newmemory handling not yet implemented */
|
int newmemory = 0;
|
||||||
|
*ptr = SWIG_TypeCast(tc, vptr, &newmemory);
|
||||||
|
if (newmemory == SWIG_CAST_NEW_MEMORY) {
|
||||||
|
assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
|
||||||
|
if (own)
|
||||||
|
*own = *own | SWIG_CAST_NEW_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ptr) *ptr = vptr;
|
if (ptr) *ptr = vptr;
|
||||||
|
|
|
||||||
|
|
@ -544,7 +544,7 @@
|
||||||
struct traits_asptr < std::vector<T> > {
|
struct traits_asptr < std::vector<T> > {
|
||||||
static int asptr(SEXP obj, std::vector<T> **val) {
|
static int asptr(SEXP obj, std::vector<T> **val) {
|
||||||
std::vector<T> *p;
|
std::vector<T> *p;
|
||||||
int res = SWIG_R_ConvertPtr(obj, (void**)&p, type_info< std::vector<T> >(), 0);
|
int res = SWIG_ConvertPtr(obj, (void**)&p, type_info< std::vector<T> >(), 0);
|
||||||
if (SWIG_IsOK(res)) {
|
if (SWIG_IsOK(res)) {
|
||||||
if (val) *val = p;
|
if (val) *val = p;
|
||||||
}
|
}
|
||||||
|
|
@ -827,7 +827,7 @@
|
||||||
static int asptr(SEXP obj, std::vector< std::vector<T> > **val) {
|
static int asptr(SEXP obj, std::vector< std::vector<T> > **val) {
|
||||||
std::vector< std::vector<T> > *p;
|
std::vector< std::vector<T> > *p;
|
||||||
Rprintf("vector of vectors - unsupported content\n");
|
Rprintf("vector of vectors - unsupported content\n");
|
||||||
int res = SWIG_R_ConvertPtr(obj, (void**)&p, type_info< std::vector< std::vector<T> > > (), 0);
|
int res = SWIG_ConvertPtr(obj, (void**)&p, type_info< std::vector< std::vector<T> > > (), 0);
|
||||||
if (SWIG_IsOK(res)) {
|
if (SWIG_IsOK(res)) {
|
||||||
if (val) *val = p;
|
if (val) *val = p;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue