Python C API and references

Discussion in 'Python' started by lallous, Nov 12, 2009.

  1. lallous

    lallous Guest

    Hello,

    Everytime I use PyObject_SetAttrString(obj, attr_name, py_val) and I don't
    need the reference to py_val I should decrement the reference after this
    call?

    So for example:

    PyObject *py_val = PyInt_FromLong(5)
    PyObject_SetAttrString(py_obj, "val", py_val);
    Py_DECREF(py_val)

    Right?

    If so, take sysmodule.c:

    if (PyObject_SetAttrString(builtins, "_", Py_None) != 0)
    return NULL;

    Shouldn't they also call Py_DECREF(Py_None) ?

    Same logic applies to PyDict_SetItemString() and the reference should be
    decrement after setting the item (ofcourse if the value is not needed).

    --
    Elias
     
    lallous, Nov 12, 2009
    #1
    1. Advertising

  2. lallous

    lallous Guest

    Hello Daniel,

    Thanks for the reply.

    >>
    >> Everytime I use PyObject_SetAttrString(obj, attr_name, py_val) and I
    >> don't
    >> need the reference to py_val I should decrement the reference after this
    >> call?

    >
    > It really depends on /how/ the object is created. If the
    > method used to create *py_val* increases the reference count
    > on the object and another function any other function is
    > used to increase the reference count, you should use Py_DECREF
    > or Py_XDECREF.
    >
    >>
    >> So for example:
    >>
    >> PyObject *py_val = PyInt_FromLong(5)
    >> PyObject_SetAttrString(py_obj, "val", py_val);
    >> Py_DECREF(py_val)
    >>
    >> Right?

    >
    > In this case is right. *PyInt_FromLong()* returns a new
    > reference: 'Return value: New reference.', which is increasing
    > the reference count and PyObject_SetAttrString does it twice,
    > then you have a reference count of two and you need to decrement
    > the initial reference counting of the object, or you will have
    > a memory leak.
    >


    Looking at the documentation, should I have understood that the passed value
    reference will be incremented and that I should decrement it if I don't need
    it?

    Or I should have understood just because of the fact that whenever we have x
    = b (be it from the C api in a form of SetAttr()) then we should know that
    b's reference will be incremented. ?

    Because, before this discussion I did not know I should decrease the
    reference after SetAttr()

    >>
    >> If so, take sysmodule.c:
    >>
    >> if (PyObject_SetAttrString(builtins, "_", Py_None) != 0)
    >> return NULL;
    >>
    >> Shouldn't they also call Py_DECREF(Py_None) ?

    >
    > No, I think that Py_None do not needs to decrease the
    > reference count...
    >


    None is an object like other objects. I think its reference must be taken
    into consideration too, for instance why there is the convenience macro:
    Py_RETURN_NONE ?

    --
    Elias
     
    lallous, Nov 12, 2009
    #2
    1. Advertising

  3. On Nov 12, 9:23 am, "lallous" <> wrote:
    > Hello,
    >
    > Everytime I use PyObject_SetAttrString(obj, attr_name, py_val) and I don't
    > need the reference to py_val I should decrement the reference after this
    > call?


    Not necessarily: it depends where py_val came from. I find the
    'ownership' model described in the docs quite helpful:

    http://docs.python.org/c-api/intro.html#reference-count-details

    It's probably better to read the docs, but here's a short version:

    If you create a reference to some Python object in a function in your
    code, you then 'own' that reference, and you're responsible for
    getting rid of it by the time the function exits. There are various
    ways this can happen: you can return the reference, thereby
    transferring ownership to the calling function; you can explicitly
    discard the reference by calling Py_DECREF; or you can transfer
    ownership by calling a function that 'steals' the reference (most
    functions in the C-API don't steal references, but rather borrow them
    for the duration of the function call).

    >
    > So for example:
    >
    > PyObject *py_val = PyInt_FromLong(5)
    > PyObject_SetAttrString(py_obj, "val", py_val);
    > Py_DECREF(py_val)
    >
    > Right?


    Yes. Here you've created the reference in the first place, so you
    should Py_DECREF it before you exit. Right after the
    PyObject_SetAttrString call is a good place to do this.

    >
    > If so, take sysmodule.c:
    >
    >         if (PyObject_SetAttrString(builtins, "_", Py_None) != 0)
    >                 return NULL;
    >
    > Shouldn't they also call Py_DECREF(Py_None) ?


    No, I don't think so. I assume you're looking at the sys_displayhook
    function? This function doesn't create new references to Py_None
    (well, except when it's about to return Py_None to the caller), so at
    this point it doesn't own any reference to Py_None: it's not
    responsible for decrementing the reference count.

    > Same logic applies to PyDict_SetItemString()


    Yes.


    --
    Mark
     
    Mark Dickinson, Nov 12, 2009
    #3
  4. En Thu, 12 Nov 2009 06:23:54 -0300, lallous <> escribió:

    > Everytime I use PyObject_SetAttrString(obj, attr_name, py_val) and I
    > don't need the reference to py_val I should decrement the reference
    > after this call?


    If you own a reference to py_val, and you don't need it anymore, you must
    decrement it. It doesn't matter if you call PyObject_SetAttrString or
    whatever, except when the called function says it "steals" a reference.

    > So for example:
    >
    > PyObject *py_val = PyInt_FromLong(5)
    > PyObject_SetAttrString(py_obj, "val", py_val);
    > Py_DECREF(py_val)
    >
    > Right?


    Yes, because PyInt_FromLong returns a new reference, and you own it.

    > If so, take sysmodule.c:
    >
    > if (PyObject_SetAttrString(builtins, "_", Py_None) != 0)
    > return NULL;
    >
    > Shouldn't they also call Py_DECREF(Py_None) ?


    No, because the reference count of Py_None was not incremented previously;
    the code doesn't own a reference to Py_None at that time. It's not the
    same as the example above.

    > Same logic applies to PyDict_SetItemString() and the reference should be
    > decrement after setting the item (ofcourse if the value is not needed).


    Yes, same as your first example.

    --
    Gabriel Genellina
     
    Gabriel Genellina, Nov 13, 2009
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roger Leigh
    Replies:
    8
    Views:
    478
    Karl Heinz Buchegger
    Nov 17, 2003
  2. Replies:
    3
    Views:
    487
    Victor Bazarov
    Nov 10, 2004
  3. DanielEKFA
    Replies:
    8
    Views:
    642
    DanielEKFA
    May 16, 2005
  4. Praveen, Tayal (IE10)
    Replies:
    0
    Views:
    402
    Praveen, Tayal (IE10)
    Mar 17, 2005
  5. Replies:
    8
    Views:
    761
    Bruno Desthuilliers
    Dec 12, 2006
Loading...

Share This Page