2011-09-08 9 views
3

파이썬 콜백을 사용하는 C++ 라이브러리가 있습니다. 콜백, 즉 PyObject *는 UnaryFunction 클래스의 객체에 저장되고 Python 객체의 생성자 Py_INCREF는 그 객체에 저장됩니다. destuctor는 Py_XDECREFs입니다. 그것이 문제이다. 인터프리터는 DECREF를 segfault합니다.파이썬 함수가 왜 가비지 수집을합니까?

제 해결책은 DECREF가 아니라는 것입니다.하지만 그건 잘못된 것처럼 보입니다. 함수의 참조 카운트를 INC/DEC에 알맞게하는 방법은 무엇이며, 더 중요한 것은 인터프리터가 다른 실제 참조가있을 때 인터프리터가 함수 본문을 GC하려고하는 이유는 무엇입니까?

편집 : 대신 segfault의 리눅스에 나는 주장은 그 말한다 실패 얻을 :

python: Objects/funcobject.c:442: func_dealloc: Assertion 'g->gc.gc_refs != (-2)' failed.

+0

이것은 메일 링리스트의 질문과 같습니다. 구글 "파이썬 메일 링리스트". 거기에서 파이썬을 잘 아는 사람들을 찾을 수 있습니다. 때로는 파이썬의 제작자/개발자도 있습니다. –

+0

관련 : http://stackoverflow.com/questions/7326762/cython-callback-works-correctly-for-function-but-not-for-bound-method/7339258#7339258 – jfs

+0

@JFSebastian, 좋은 방법이지만 방법은 범위를 벗어나지 않습니다. 이 문제는 간단한'def myfunc (x) : "를 가진 단순한 플랫 스크립트에서 보여집니다. 콜백을 사용하는 부분을 주석 처리하면 스크립트의 끝 부분에서 myfunc()를 호출 할 수 있습니다. – Adam

답변

0

는 Py_INCREF 단순히 실제로 refcount가를 증가하지 않는 나타납니다 소멸자에 Py_XDECREF를 호출

이 같은 뭔가를 생각하는 날 리드 .

1

충돌이 사용되는 객체를 GC하려고하는 것이 필요 의미하지 않는다. 또한 해석기 잠금없이 파이썬 코드를 호출한다는 것을 의미 할 수도 있습니다.

void MyCallback(myfunc, myarg) 
{ 
    ... 
    PyGILState_STATE gilstate = PyGILState_Ensure(); 
    try { 
      myfunc(myarg); 
    } catch (...) { 
     ... 
    } 
    PyGILState_Release(gilstate); 

    // myfunc goes out of scope here --> CRASH because we no longer own the GIL 
} 

간단한 솔루션 :

... 
try { 
    scopefunc = myfunc; 
    myfunc = emptyfunc(); 
    scopefunc(myarg); 
} ... 
+0

사실, 저는 전혀 GIL을 건드리지 않는다. GIL이 명시 적으로 해제되지 않으면 GIL이 해제되지 않는다는 것을 알기 때문에, C++ 코드는 단순히 PyEval_CallObject()를 사용하여 함수를 호출한다. segfault가 다음과 같기 때문에 콜렉션된다고 가정한다 :'Objects/funcobject.c : 442 : func_dealloc : 어설 션 'g-> gc.gc_refs! = (-2)'failed.' 그리고 dealloc과 GC 참조에 대해 얘기하고 있습니다 .. – Adam

+0

만약 스레드가 하나뿐이라면 더 간단해야합니다. incrementf/decref가 일치하지 않고 함수를 포함하는 각 단계 전후에'sys.getrefcount'를 호출하면 몇 가지 실마리를 얻을 수 있습니다 –

관련 문제