#1071 [python] Strange behaviour of temporary objects

python (259)

maybe this is me misunderstanding some deep memory allocation issues, but I noticed a quite strange behaviour with SWIG and temporary objects. If this is the case, I'd like to have the matching pointer to the documentation or ask you to consider this as a documentation bug :-)
See attached reduced test case. When calling make.sh, I expect to have the same result (1.0) twice, but I get:
A: 1.0
B: 0.0

I am using debian, python version 2.5, and swig 1.3.40, g++ 4.3.4, though this is not the only configuration showing this behaviour (Kubuntu 9.10 with default packages does the same).

Best regards,



  • onko

    Boiled-down test case for access problem/bug

  • William Fulton
    William Fulton

    Modifying your test.i file to:

    %module test

    #include "test.hh"

    %feature("exceptvar") {
    printf("%p In variable wrapper ... $symname\n", arg1);
    %exception {
    printf("%p In function... $symname\n", arg1);

    %exception v::v {
    printf("%p In constructor... $symname\n", result);
    %exception comp::comp {
    printf("%p In constructor... $symname\n", result);

    %exception v::~v() {
    printf("%p In destructor... $symname\n", arg1);
    %exception comp::~comp() {
    printf("%p In destructor... $symname\n", arg1);
    %include "test.hh"

    With just the one line of python code:

    print "B:", comp(v(1,1,1), v(2,2,2)).a.x

    The output is:

    B:0x45ae698 In constructor... new_v
    0x45af200 In constructor... new_v
    0x45af470 In constructor... new_comp
    0x45af200 In destructor... delete_v
    0x45ae698 In destructor... delete_v
    0x45af470 In variable wrapper ... comp_a_get
    0x45af470 In destructor... delete_comp
    0x45af470 In variable wrapper ... v_x_get

    So v_x_get uses deleted memory (after delete_comp is called). Note the address of comp is the same as comp::x as x is at the first member variable. Valgrind confirms the problem:

    ==26786== Invalid read of size 8
    ==26786== at 0x4036746: _wrap_v_x_get (in /home/william/swig/trunk/Examples/william/temp_access/_test.so)
    ==26786== by 0x8065B83: PyObject_CallFunction (in /usr/bin/python2.6)
    ==26786== by 0x80940C6: PyObject_GenericGetAttr (in /usr/bin/python2.6)
    ==26786== by 0x80B280E: ??? (in /usr/bin/python2.6)
    ==26786== by 0x80DDD1F: PyEval_EvalFrameEx (in /usr/bin/python2.6)
    ==26786== by 0x80E2806: PyEval_EvalCodeEx (in /usr/bin/python2.6)
    ==26786== by 0x80E2906: PyEval_EvalCode (in /usr/bin/python2.6)
    ==26786== by 0x81005AC: PyRun_FileExFlags (in /usr/bin/python2.6)
    ==26786== by 0x8100811: PyRun_SimpleFileExFlags (in /usr/bin/python2.6)
    ==26786== by 0x805DE5B: Py_Main (in /usr/bin/python2.6)
    ==26786== by 0x805D03A: main (in /usr/bin/python2.6)

    I don't have the solution nor the expertise about the python reference counting, so all I can do is confirm the behaviour will provide undefined results, even though I see the correct result of 1.0. However the equivalent code in Java is known to be problematic and the solution is to enforce a reference in the 'comp' instance to 'a' so that it is not garbage collected early.

  • Olly Betts
    Olly Betts

    • summary: Strange behaviour of temporary objects --> [python] Strange behaviour of temporary objects