2011-08-08 16 views
7

Bất cứ khi nào tôi gọi chức năng của mình, mức sử dụng bộ nhớ tăng khoảng 10 triệu mỗi cuộc gọi, vì vậy tôi nghĩ rằng có một số rò rỉ bộ nhớ ở đây.Tôi nên đặt Py_INCREF và Py_DECREF vào khối này trong phần mở rộng của Python C ở đâu?

.... 
PyObject *pair = PyTuple_New(2), *item = PyList_New(0); 

PyTuple_SetItem(pair, 0, PyInt_FromLong(v[j])); 

if(v[j] != DISTANCE_MAX && (p[j] || d[0][j])){ 
    jp=j; 
    while(jp!=istart) { 
    PyList_Append(item, PyInt_FromLong(jp)); 
    jp=p[jp]; 
    } 

    PyList_Append(item, PyInt_FromLong(jp)); 

    PyList_Reverse(item); 
} 

PyTuple_SetItem(pair, 1, item); 

return pair; 
.... 

Khi tôi đọc document, một số cuộc gọi như

void 
bug(PyObject *list) 
{ 
    PyObject *item = PyList_GetItem(list, 0); 

    PyList_SetItem(list, 1, PyInt_FromLong(0L)); 
    PyObject_Print(item, stdout, 0); /* BUG! */ 
} 

cần phải đưa số lượng tài liệu tham khảo như thế này

void 
no_bug(PyObject *list) 
{ 
    PyObject *item = PyList_GetItem(list, 0); 

    Py_INCREF(item); 
    PyList_SetItem(list, 1, PyInt_FromLong(0L)); 
    PyObject_Print(item, stdout, 0); 
    Py_DECREF(item); 
} 

Vì vậy, tôi nên đặt Py_INCREF và Py_DECREF ở đâu trên chức năng của tôi?

Trả lời

10

Đối tượng bạn tạo với PyInt_FromLong() và bạn thêm vào danh sách nên được giữ trong một biến cục bộ.

Lý do là ownership rules: PyInt_FromLong() tạo tham chiếu mà bạn sở hữu. Trong cuộc gọi đến PyTuple_SetItem(), bạn mất quyền sở hữu này một lần nữa, bởi vì PyTuple_SetItem() "đánh cắp" nó từ bạn, vì vậy bạn không cần phải quan tâm. Nhưng PyList_Append() không làm như vậy, nó làm tăng số lần truy cập. Để có đối tượng được GC'ed chính xác, bạn phải giải phóng quyền sở hữu của mình bằng cách DECREF'ing.

Vì vậy, thay vì PyList_Append (item, PyInt_FromLong (jp)), bạn thực hiện như sau:

PyObject * jpo = PyInt_FromLong(jp); 
// do some error checking here 
PyList_Append(item, jpo); 
Py_DECREF(jpo); 

Điều này sẽ làm cho chương trình làm điều đúng.

0

Khi một đối tượng được tạo ra, refcount của nó sẽ là 1, vì vậy sau này:

my_item = PyInt_FromLong(jp) 

đối tượng tại my_item sẽ có một refcount của 1.

Khi bạn lưu trữ một mục vào một container , số lượng tài liệu tham khảo của sản phẩm được tăng lên để các mục sẽ được giữ lại, vì vậy sau này:

PyList_Append(my_list, my_item); 

đối tượng tại my_item sẽ có một refcou nt của 2.

Do đó, dòng này:

PyList_Append(item, PyInt_FromLong(jp)); 

sẽ tạo ra một đối tượng với refcount 1 và lưu trữ nó trong danh sách, incrementing refcount của đối tượng để 2.

+8

Vậy ... anh ấy nên đặt 'Py_INCREF' và' Py_DECREF' ở đâu? Bạn không trả lời câu hỏi của mình. – agf