custodian=xxx memory problems
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
PyBindGen |
Fix Released
|
Medium
|
Unassigned |
Bug Description
--- example.hh ---
#include <iostream>
class A {
public:
A(int val = 0): mVal(val) { std::cout << "A constructor." << std::endl; }
virtual ~A() {}
int val() const { return mVal; }
void val(int x) { mVal = x; }
private:
int mVal;
};
class B {
public:
B(): mAptr(new A) { std::cout << "B constructor with " << mAptr << std::endl; }
virtual ~B() {}
A* Aptr() { return mAptr; }
private:
A* mAptr;
};
--- example-gen.py ---
from pybindgen import *
import sys
mod = Module("example")
mod.add_
a = mod.add_class("A", allow_subclassi
a.add_construct
a.add_instance_
b = mod.add_class("B", allow_subclassi
b.add_construct
#b.add_
#b.add_
b.add_method(
f = open("example.C", "w")
mod.generate(
f.close()
--- test.py ---
import example
b = example.B()
a = b.Aptr()
print "Before changing: ", a.val, b.Aptr().val
a.val = 10
print "After changing: ", a.val, b.Aptr().val
--- valgrind ---
==10091== Invalid read of size 8
==10091== at 0x6058AFB: PyA__tp_clear(PyA*) (example.C:138)
==10091== by 0x6058B75: _wrap_PyA_
==10091== by 0x43DC71: list_dealloc (listobject.c:306)
==10091== by 0x44D832: dict_dealloc (dictobject.c:911)
==10091== by 0x6058F43: PyB__tp_clear(PyB*) (example.C:294)
==10091== by 0x6058FE1: _wrap_PyB_
==10091== by 0x44C096: insertdict (dictobject.c:459)
==10091== by 0x44E656: PyDict_SetItem (dictobject.c:701)
==10091== by 0x45010D: _PyModule_Clear (moduleobject.
==10091== by 0x4B53A9: PyImport_Cleanup (import.c:439)
==10091== by 0x4C2C34: Py_Finalize (pythonrun.c:434)
==10091== by 0x4185C1: Py_Main (main.c:625)
==10091== Address 0x602a660 is 0 bytes inside a block of size 16 free'd
==10091== at 0x4C24A7A: operator delete(void*) (vg_replace_
==10091== by 0x605933A: A::~A() (example.hh:8)
==10091== by 0x6058B0D: PyA__tp_clear(PyA*) (example.C:138)
==10091== by 0x6058B75: _wrap_PyA_
==10091== by 0x43DC71: list_dealloc (listobject.c:306)
==10091== by 0x44D832: dict_dealloc (dictobject.c:911)
==10091== by 0x6058F43: PyB__tp_clear(PyB*) (example.C:294)
==10091== by 0x6058FE1: _wrap_PyB_
==10091== by 0x44C096: insertdict (dictobject.c:459)
==10091== by 0x44E656: PyDict_SetItem (dictobject.c:701)
==10091== by 0x45010D: _PyModule_Clear (moduleobject.
==10091== by 0x4B53A9: PyImport_Cleanup (import.c:439)
Related branches
Changed in pybindgen: | |
status: | New → Confirmed |
importance: | Undecided → Medium |
Changed in pybindgen: | |
status: | Fix Committed → Fix Released |
The test program calls b.Aptr() multiple times, which creates multiple wrappers for class A. At the end of the simulation, each distinct wrapper will try to deallocate the same A instance, causing the double-free.
We need to add a option to create a wrapper which knows the C++ instance is shared and doesn't try to free it. Unfortunately that means adding bytes to the python wrapper structure, but that's life.