@@ -114,9 +114,13 @@ class cpp_function : public function {
114
114
object name () const { return attr (" __name__" ); }
115
115
116
116
protected:
117
+ using unique_function_record = std::unique_ptr<detail::function_record, void (*)(detail::function_record *)>;
118
+
117
119
// / Space optimization: don't inline this frequently instantiated fragment
118
- PYBIND11_NOINLINE std::unique_ptr<detail::function_record> make_function_record () {
119
- return std::unique_ptr<detail::function_record>(new detail::function_record ());
120
+ PYBIND11_NOINLINE unique_function_record make_function_record () {
121
+ // `destruct<true>(function_record)`: `initialize_generic` copies strings and
122
+ // takes care of cleaning up in case of exceptions.
123
+ return unique_function_record (new detail::function_record (), destruct<false >);
120
124
}
121
125
122
126
// / Special internal constructor for functors, lambda functions, etc.
@@ -247,7 +251,7 @@ class cpp_function : public function {
247
251
};
248
252
249
253
// / Register a function call with Python (generic non-templated code goes here)
250
- void initialize_generic (std::unique_ptr<detail::function_record> &&unique_rec, const char *text,
254
+ void initialize_generic (unique_function_record &&unique_rec, const char *text,
251
255
const std::type_info *const *types, size_t args) {
252
256
auto rec = unique_rec.get ();
253
257
@@ -486,6 +490,7 @@ class cpp_function : public function {
486
490
}
487
491
488
492
// / When a cpp_function is GCed, release any memory allocated by pybind11
493
+ template <bool DeleteStrings = true >
489
494
static void destruct (detail::function_record *rec) {
490
495
// If on Python 3.9, check the interpreter "MICRO" (patch) version.
491
496
// If this is running on 3.9.0, we have to work around a bug.
@@ -497,14 +502,19 @@ class cpp_function : public function {
497
502
detail::function_record *next = rec->next ;
498
503
if (rec->free_data )
499
504
rec->free_data (rec);
500
- std::free ((char *) rec->name );
501
- std::free ((char *) rec->doc );
502
- std::free ((char *) rec->signature );
503
- for (auto &arg: rec->args ) {
504
- std::free (const_cast <char *>(arg.name ));
505
- std::free (const_cast <char *>(arg.descr ));
506
- arg.value .dec_ref ();
505
+ // During initialization, these strings might not have been copied yet,
506
+ // so they cannot be freed. Once the function has been created, they can.
507
+ if (DeleteStrings) {
508
+ std::free ((char *) rec->name );
509
+ std::free ((char *) rec->doc );
510
+ std::free ((char *) rec->signature );
511
+ for (auto &arg: rec->args ) {
512
+ std::free (const_cast <char *>(arg.name ));
513
+ std::free (const_cast <char *>(arg.descr ));
514
+ }
507
515
}
516
+ for (auto &arg: rec->args )
517
+ arg.value .dec_ref ();
508
518
if (rec->def ) {
509
519
std::free (const_cast <char *>(rec->def ->ml_doc ));
510
520
// Python 3.9.0 decref's these in the wrong order; rec->def
0 commit comments