Re: Python C API and references
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Python C API and references
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Python C API and references
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. [quote] int PyObject_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v) Set the value of the attribute named attr_name, for object o, to the value v. Returns -1 on failure. This is the equivalent of the Python statement o.attr_name = v. int PyObject_SetAttrString(PyObject *o, const char *attr_name, PyObject *v) Set the value of the attribute named attr_name, for object o, to the value v. Returns -1 on failure. This is the equivalent of the Python statement o.attr_name = v. [/quote] 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 -- http://mail.python.org/mailman/listinfo/python-list
Python C API and references
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 -- http://mail.python.org/mailman/listinfo/python-list