Title: Improve guidelines for GC protocol implementation for heap types · Issue #138292 · python/cpython · GitHub
Open Graph Title: Improve guidelines for GC protocol implementation for heap types · Issue #138292 · python/cpython
X Title: Improve guidelines for GC protocol implementation for heap types · Issue #138292 · python/cpython
Description: This is a follow-up to #125962 which added some guidelines: Use type->tp_alloc instead of PyObject_New and PyObject_GC_New. Use type->tp_free instead of PyObject_Free and PyObject_GC_Del. Those two recommendations were introduced to faci...
Open Graph Description: This is a follow-up to #125962 which added some guidelines: Use type->tp_alloc instead of PyObject_New and PyObject_GC_New. Use type->tp_free instead of PyObject_Free and PyObject_GC_Del. Those two...
X Description: This is a follow-up to #125962 which added some guidelines: Use type->tp_alloc instead of PyObject_New and PyObject_GC_New. Use type->tp_free instead of PyObject_Free and PyObject_GC_Del. Tho...
Opengraph URL: https://github.com/python/cpython/issues/138292
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Improve guidelines for GC protocol implementation for heap types","articleBody":"This is a follow-up to https://github.com/python/cpython/pull/125962 which added some guidelines:\n\n- Use `type-\u003etp_alloc` instead of `PyObject_New` and `PyObject_GC_New`.\n- Use `type-\u003etp_free` instead of `PyObject_Free` and `PyObject_GC_Del`.\n\nThose two recommendations were introduced to facilitate adding the `Py_TPFLAGS_HAVE_GC` flag to a heap type (those types must (should?) implement the GC protocol, at least according to the docs: https://docs.python.org/3/c-api/gcsupport.html#supporting-cycle-detection).\n\nNow, the docs should indicate that:\n\n- `type-\u003etp_alloc` may call `PyObject_GC_Track`, depending on `Py_TPFLAGS_HAVE_GC`. Some users could be surprised by this (like me in https://github.com/python/cpython/pull/138266).\n- https://docs.python.org/3.14/c-api/gcsupport.html#supporting-cycle-detection should be updated because it mentions using `PyObject_GC_New`, which itself mentions using `tp_alloc` directly. Better to just mention `tp_alloc`.\n\nWhat I am actually worried about is:\n\n\u003e Constructors for container types must conform to two rules:\n\u003e\n\u003e - The memory for the object must be allocated using [PyObject_GC_New](https://docs.python.org/3.14/c-api/gcsupport.html#c.PyObject_GC_New) or [PyObject_GC_NewVar](https://docs.python.org/3.14/c-api/gcsupport.html#c.PyObject_GC_NewVar).\n\u003e - Once all the fields which may contain references to other containers are initialized, it must call [PyObject_GC_Track()](https://docs.python.org/3.14/c-api/gcsupport.html#c.PyObject_GC_Track).\n\nNow, `tp_alloc` automatically calls `PyObject_GC_Track` so users won't be able to pre-initialize fields, so I suggest that we mention this.\n\n\u003cdetails\u003e\n\u003csummary\u003eOutdated discussion\u003c/summary\u003e\n\nIf people need to first initialize fields, maybe we should recommend constructing them first:\n\n```c\nstatic PyObject *\nobject_new(PyTypeObject *type)\n{\n T *self = NULL;\n PyObject *f1, *f2, *f3;\n \n f1 = do1();\n if (f1 == NULL) { goto error_pre_init; }\n f2 = do2();\n if (f2 == NULL) { goto error_pre_init; }\n f3 = do3();\n if (f3 == NULL) { goto error_pre_init; }\n \n self = (T *)type-\u003etp_alloc(type, 0);\n if (self == NULL) {\n goto error_pre_init;\n }\n self-\u003ef1 = f1;\n self-\u003ef2 = f2;\n self-\u003ef3 = f3;\n f1 = f2 = f3 = NULL;\n\n if (finalize(self) \u003c 0) {\n goto error;\n }\n return (PyObject *)self;\n\nerror_pre_init:\n Py_XDECREF(f1);\n Py_XDECREF(f2);\n Py_XDECREF(f3);\n return NULL;\n\nerror_post_init:\n Py_DECREF(self);\n return NULL;\n}\n```\n\u003c/details\u003e\n\ncc @ZeroIntensity ","author":{"url":"https://github.com/picnixz","@type":"Person","name":"picnixz"},"datePublished":"2025-08-31T13:19:21.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/138292/cpython/issues/138292"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:46cec6f7-bee1-25e1-3be6-fa958656dc85 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 96C2:11A36F:403B5:54006:696B5A14 |
| html-safe-nonce | 467c8364a9b890ea5bf1d3d28c1029963e4016d93e62f306093b83e18875e2e4 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5NkMyOjExQTM2Rjo0MDNCNTo1NDAwNjo2OTZCNUExNCIsInZpc2l0b3JfaWQiOiIzMTg5NDgyMDY2MjY4NjA5MDQ0IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 0d558cccf279cd45c9702609e7c2811495a2348fee61ef0f08909969f19aeae1 |
| hovercard-subject-tag | issue:3370256446 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/138292/issue_layout |
| twitter:image | https://opengraph.githubassets.com/e038c48348a0f4c40d9d9b7d9be8b99dc0a146ae9d7cdf8d46808ce1bc384c67/python/cpython/issues/138292 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/e038c48348a0f4c40d9d9b7d9be8b99dc0a146ae9d7cdf8d46808ce1bc384c67/python/cpython/issues/138292 |
| og:image:alt | This is a follow-up to #125962 which added some guidelines: Use type->tp_alloc instead of PyObject_New and PyObject_GC_New. Use type->tp_free instead of PyObject_Free and PyObject_GC_Del. Those two... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | picnixz |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5f99f7c1d70f01da5b93e5ca90303359738944d8ab470e396496262c66e60b8d |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 82560a55c6b2054555076f46e683151ee28a19bc |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width