mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15:12 +00:00
Stash std::strings used for tp_name in internals
Types need `tp_name` set to a C-style string, but the current `strdup` ends up with a leak (issue #977). This avoids the strdup by storing the `std::string` in internals so that during interpreter shutdown it will be properly destroyed.
This commit is contained in:
parent
7437c69500
commit
2640c950ca
@ -518,12 +518,11 @@ inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
module = rec.scope.attr("__name__");
|
||||
}
|
||||
|
||||
auto full_name = c_str(
|
||||
#if !defined(PYPY_VERSION)
|
||||
const auto full_name = module ? str(module).cast<std::string>() + "." + rec.name
|
||||
: std::string(rec.name);
|
||||
#else
|
||||
const auto full_name = std::string(rec.name);
|
||||
module ? str(module).cast<std::string>() + "." + rec.name :
|
||||
#endif
|
||||
rec.name);
|
||||
|
||||
char *tp_doc = nullptr;
|
||||
if (rec.doc && options::show_user_defined_docstrings()) {
|
||||
@ -556,7 +555,7 @@ inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
#endif
|
||||
|
||||
auto type = &heap_type->ht_type;
|
||||
type->tp_name = strdup(full_name.c_str());
|
||||
type->tp_name = full_name;
|
||||
type->tp_doc = tp_doc;
|
||||
type->tp_base = type_incref((PyTypeObject *)base);
|
||||
type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
|
||||
|
@ -494,6 +494,7 @@ struct internals {
|
||||
std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators;
|
||||
std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions
|
||||
std::vector<PyObject *> loader_patient_stack; // Used by `loader_life_support`
|
||||
std::forward_list<std::string> static_strings; // Stores the std::strings backing detail::c_str()
|
||||
PyTypeObject *static_property_type;
|
||||
PyTypeObject *default_metaclass;
|
||||
PyObject *instance_base;
|
||||
@ -688,6 +689,16 @@ using expand_side_effects = bool[];
|
||||
#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN) pybind11::detail::expand_side_effects{ ((PATTERN), void(), false)..., false }
|
||||
#endif
|
||||
|
||||
/// Constructs a std::string with the given arguments, stores it in `internals`, and returns its
|
||||
/// `c_str()`. Such strings objects have a long storage duration -- the internal strings are only
|
||||
/// cleared when the program exits or after interpreter shutdown (when embedding), and so are
|
||||
/// suitable for c-style strings needed by Python internals (such as PyTypeObject's tp_name).
|
||||
template <typename... Args> const char *c_str(Args &&...args) {
|
||||
auto &strings = get_internals().static_strings;
|
||||
strings.emplace_front(std::forward<Args>(args)...);
|
||||
return strings.front().c_str();
|
||||
}
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
|
||||
/// Returns a named pointer that is shared among all extension modules (using the same
|
||||
|
Loading…
Reference in New Issue
Block a user