在处理C代码时,是否存在Python引用计数/垃圾收集问题?

在处理C代码时,是否存在Python引用计数/垃圾收集问题?,python,garbage-collection,scheme,reference-counting,python-c-api,Python,Garbage Collection,Scheme,Reference Counting,Python C Api,纯粹为了见鬼,我决定创建一个脚本,这样您就可以在Scheme程序中嵌入Python。我已经能够调用Python的C API,但我还没有真正考虑内存管理 mzscheme的FFI的工作方式是,我可以调用一个函数,如果该函数返回指向PyObject的指针,那么我可以让它自动增加引用计数。然后,我可以注册一个终结器,当Scheme对象被垃圾收集时,它将减少引用计数。我已经看过了,第一眼就看不出有任何问题(尽管在某些情况下它可能是次优的)。有什么我不知道的吗 而且,我很难做出正确的判断。在这里我需要记住

纯粹为了见鬼,我决定创建一个脚本,这样您就可以在Scheme程序中嵌入Python。我已经能够调用Python的C API,但我还没有真正考虑内存管理

mzscheme的FFI的工作方式是,我可以调用一个函数,如果该函数返回指向
PyObject
的指针,那么我可以让它自动增加引用计数。然后,我可以注册一个终结器,当Scheme对象被垃圾收集时,它将减少引用计数。我已经看过了,第一眼就看不出有任何问题(尽管在某些情况下它可能是次优的)。有什么我不知道的吗

而且,我很难做出正确的判断。在这里我需要记住什么?特别是,如何让Python意识到我有一个对某个对象的引用,以便在我仍在使用它时它不会收集它?

您的链接位置正确。文档中的扩展和嵌入以及Python/CAPI部分将解释如何使用CAPI

引用计数是使用C API时令人讨厌的部分之一。主要的窍门是保持一切正常:根据您调用的API函数,您可能拥有也可能不拥有对您得到的对象的引用。小心地了解您是否拥有它(因此不能忘记将其减少或提供给将要窃取它的东西)或正在借用它(并且必须增加它以保留它,并可能在您的功能期间使用它)。与此相关的最常见错误是1)错误地记住您是否拥有某个特定函数返回的引用,2)相信您可以安全地借用引用更长的时间


您不必为循环垃圾收集器执行任何特殊操作。它只是用来修补引用计数中的一个缺陷,不需要直接访问。

我所知道的引用计数和C API最大的问题是
\u del\u
问题。当你有一个借来的参考资料时,你认为你可以不增加就离开,因为当你使用这个参考资料时,你不会放弃GIL。但是,如果您最终删除了一个对象(例如,通过从列表中删除它),则可能会触发一个
\uuu del\uuu
调用,这可能会删除您从脚下借用的引用。非常棘手


如果你一拿到所有借来的参考资料就增加(当然是减少),那应该不会有任何问题。

。。。Python对循环结构使用引用计数和垃圾收集器?这是一个相当大的缺陷。设计类。在任何情况下,如果参与python端循环的任何值都暴露于scheme中,这听起来会让Jason觉得事情更“有趣”。@Jason,仅增量借用引用。某些函数返回已递增的新引用。递增这些引用将导致内存泄漏。@Eli,在CPython中杀死对象的主要策略是重新计数。由于refcounting不会在其他不可访问的引用循环上进行拾取,因此它增加了一个(可选,默认为on)循环垃圾收集器。这种扩展对于防止允许任意引用的任何refcounted系统中的内存泄漏是必要的。这只是一个设计缺陷,因为重新计数是一个设计缺陷(当然,有些人会声称这是一个设计缺陷)。@Jason,不,这是问题所在!有时借用引用(需要增加引用以拥有对对象的引用),有时通过调用函数偷取引用并已经拥有它;在这种情况下,增量可能会导致内存泄漏。类似地,何时和是否取消引用取决于某个函数是否窃取了您的引用,这种情况会发生。不同的函数提供或借用它们返回的引用,窃取或借用它们收到的引用。记住你正在使用的函数是什么,这就是为什么这可能是一个gotchas的来源。@Eli,你没有对我说清楚;我以为你是在明确声称用cyclefinder增加重新计数是一个设计问题。你是否喜欢refcouting是一个更大的问题,更像是一个宗教问题而不是技术问题。