@@ -1406,33 +1406,46 @@ class module_ : public object {
14061406 return reinterpret_borrow<module_>(m);
14071407 }
14081408
1409+ // / Must be a POD type, and must hold enough entries for all of the possible slots PLUS ONE for
1410+ // / the sentinel (0) end slot.
1411+ using slots_array = std::array<PyModuleDef_Slot, 4 >;
1412+
14091413 /* * \rst
14101414 Initialized a module def for use with multi-phase module initialization.
14111415
14121416 ``def`` should point to a statically allocated module_def.
14131417 ``slots`` must already contain a Py_mod_exec or Py_mod_create slot and will be filled with
1414- additional slots (and the empty terminator slot) from the supplied options .
1418+ additional slots from the supplied options (and the empty sentinel slot).
14151419 \endrst */
14161420 template <typename ... Options>
14171421 static object initialize_multiphase_module_def (const char *name,
14181422 const char *doc,
14191423 module_def *def,
1420- std::vector<PyModuleDef_Slot> &slots,
1424+ slots_array &slots,
14211425 Options &&...options) {
1422- // remove zero end sentinel, if present
1423- while (!slots.empty () && slots.back ().slot == 0 ) {
1424- slots.pop_back ();
1426+ size_t next_slot = 0 ;
1427+ size_t term_slot = slots.size () - 1 ;
1428+
1429+ // find the end of the supplied slots
1430+ while (next_slot < term_slot && slots[next_slot].slot != 0 ) {
1431+ ++next_slot;
14251432 }
14261433
14271434 bool nogil PYBIND11_MAYBE_UNUSED = detail::gil_not_used_option (options...);
14281435 if (nogil) {
14291436#if defined(Py_mod_gil) && defined(Py_GIL_DISABLED)
1430- slots.emplace_back (PyModuleDef_Slot{Py_mod_gil, Py_MOD_GIL_NOT_USED});
1437+ if (next_slot >= term_slot) {
1438+ pybind11_fail (" initialize_multiphase_module_def: not enough space in slots" );
1439+ }
1440+ slots[next_slot++] = {Py_mod_gil, Py_MOD_GIL_NOT_USED});
14311441#endif
14321442 }
14331443
1434- // must have a zero end sentinel
1435- slots.emplace_back (PyModuleDef_Slot{0 , nullptr });
1444+ // slots must have a zero end sentinel
1445+ if (next_slot > term_slot) {
1446+ pybind11_fail (" initialize_multiphase_module_def: not enough space in slots" );
1447+ }
1448+ slots[next_slot++] = {0 , nullptr };
14361449
14371450 // module_def is PyModuleDef
14381451 // Placement new (not an allocation).
@@ -1442,7 +1455,7 @@ class module_ : public object {
14421455 /* m_doc */ options::show_user_defined_docstrings () ? doc : nullptr ,
14431456 /* m_size */ 0 ,
14441457 /* m_methods */ nullptr ,
1445- /* m_slots */ slots. data () ,
1458+ /* m_slots */ & slots[ 0 ] ,
14461459 /* m_traverse */ nullptr ,
14471460 /* m_clear */ nullptr ,
14481461 /* m_free */ nullptr };
0 commit comments