Fix intermittent crash due to incorrect pybind11 object scope
Fixes [ch6276]
@@ -109,11 +109,13 @@ private:
// avoid one interpreter roundtrip
auto npstrencode = py::module::import("numpy").attr("str").attr("encode");
- // TODO: ideally we would encode directly here without the intermediate
- // unicode object
- // TODO add test for different memory orderings
-
+ // return status
int rc;
+ // encoded object: this must live outside the if block or else it may be
+ // GC'd
+ // putting outside for loop to avoid repeat unused
+ // construction
+ py::object u_encoded;
// loop over array objects and write to output buffer
size_t idx = 0;
@@ -121,15 +123,17 @@ private:
// don't encode if we already have bytes
if (PyUnicode_Check(u.ptr())) {
// TODO see if we can do this with PyUnicode_AsUTF8String
- py::object u_encoded = npstrencode(u);
- rc = PyBytes_AsStringAndSize(u_encoded.ptr(), const_cast<char **>(&input_p),
- &sz);
+ u_encoded = npstrencode(u);
+ rc = PyBytes_AsStringAndSize(u_encoded.ptr(),
+ const_cast<char **>(&input_p), &sz);
} else {
- rc = PyBytes_AsStringAndSize(u.ptr(), const_cast<char **>(&input_p), &sz);
+ rc = PyBytes_AsStringAndSize(u.ptr(), const_cast<char **>(&input_p),
+ &sz);
}
if (rc == -1) {
- throw std::runtime_error("PyBytes_AsStringAndSize failed to encode string");
+ throw std::runtime_error(
+ "PyBytes_AsStringAndSize failed to encode string");
}
// record the offset (equal to the current bytes written)
@@ -194,7 +198,8 @@ private:
rc = PyBytes_AsStringAndSize(o, const_cast<char **>(&input_p), &sz);
if (rc == -1) {
- throw std::runtime_error("PyBytes_AsStringAndSize failed to encode string");
+ throw std::runtime_error(
+ "PyBytes_AsStringAndSize failed to encode string");
}
// record the offset (equal to the current bytes written)
