static allocation for PyModuleDef, to avoid leak check errors. (#2413)

* Initializing PyModuleDef object with PyModuleDef_HEAD_INIT.

Python 3.8 documentation: m_base - Always initialize this member to PyModuleDef_HEAD_INIT.

Long-standing (since first github commit in 2015), inconsequential bug.

Also removing inconsequential Py_INCREF(def): PyModule_Create() resets the reference count to 1.

* git rebase master

* moving static PyModuleDef declaration to global scope, as requested by @wjakob

* renaming the two new macros, to start with PYBIND11_DETAIL_MODULE
This commit is contained in:
Ralf W. Grosse-Kunstleve 2020-09-26 22:55:11 -07:00 committed by GitHub
parent 3c7ef56bb6
commit d159a56338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 10 deletions

View File

@ -307,13 +307,26 @@ extern "C" {
}); });
} }
\endrst */ \endrst */
#if PY_MAJOR_VERSION >= 3
#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \
static PyModuleDef PYBIND11_CONCAT(pybind11_module_def_, name);
#define PYBIND11_DETAIL_MODULE_CREATE(name) \
auto m = pybind11::module( \
PYBIND11_TOSTRING(name), nullptr, \
&PYBIND11_CONCAT(pybind11_module_def_, name));
#else
#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name)
#define PYBIND11_DETAIL_MODULE_CREATE(name) \
auto m = pybind11::module(PYBIND11_TOSTRING(name));
#endif
#define PYBIND11_MODULE(name, variable) \ #define PYBIND11_MODULE(name, variable) \
PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \
PYBIND11_MAYBE_UNUSED \ PYBIND11_MAYBE_UNUSED \
static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \
PYBIND11_PLUGIN_IMPL(name) { \ PYBIND11_PLUGIN_IMPL(name) { \
PYBIND11_CHECK_PYTHON_VERSION \ PYBIND11_CHECK_PYTHON_VERSION \
PYBIND11_ENSURE_INTERNALS_READY \ PYBIND11_ENSURE_INTERNALS_READY \
auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ PYBIND11_DETAIL_MODULE_CREATE(name) \
try { \ try { \
PYBIND11_CONCAT(pybind11_init_, name)(m); \ PYBIND11_CONCAT(pybind11_init_, name)(m); \
return m.ptr(); \ return m.ptr(); \

View File

@ -862,18 +862,24 @@ public:
PYBIND11_OBJECT_DEFAULT(module_, object, PyModule_Check) PYBIND11_OBJECT_DEFAULT(module_, object, PyModule_Check)
/// Create a new top-level Python module with the given name and docstring /// Create a new top-level Python module with the given name and docstring
explicit module_(const char *name, const char *doc = nullptr) {
if (!options::show_user_defined_docstrings()) doc = nullptr;
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
auto *def = new PyModuleDef(); explicit module_(const char *name, const char *doc = nullptr, PyModuleDef *def = nullptr) {
std::memset(def, 0, sizeof(PyModuleDef)); if (!def) def = new PyModuleDef();
def->m_name = name; def = new (def) PyModuleDef { // Placement new (not an allocation).
def->m_doc = doc; /* m_base */ PyModuleDef_HEAD_INIT,
def->m_size = -1; /* m_name */ name,
Py_INCREF(def); /* m_doc */ options::show_user_defined_docstrings() ? doc : nullptr,
/* m_size */ -1,
/* m_methods */ nullptr,
/* m_slots */ nullptr,
/* m_traverse */ nullptr,
/* m_clear */ nullptr,
/* m_free */ nullptr
};
m_ptr = PyModule_Create(def); m_ptr = PyModule_Create(def);
#else #else
m_ptr = Py_InitModule3(name, nullptr, doc); explicit module_(const char *name, const char *doc = nullptr) {
m_ptr = Py_InitModule3(name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
#endif #endif
if (m_ptr == nullptr) if (m_ptr == nullptr)
pybind11_fail("Internal error in module_::module_()"); pybind11_fail("Internal error in module_::module_()");