-1

So I have this c extension function which loads a python module and uses a list of c++ strings to get a specific global attribute from that module:

PyObject* get_global_constant(const char* module_name, std::vector<std::string> constant_names) {
    /* Gets a global variable from a Python module */
    PyObject *temp_module = PyImport_ImportModule(module_name);
    PyObject *global_var = PyImport_AddModule(module_name);
    for (std::string constant : constant_names) {
        global_var = PyObject_GetAttrString(global_var, constant.c_str());
    }
    Py_DECREF(temp_module);
    return global_var;
}

Does this leak?

  • I usually use something like boost_python to handle some of the interface, but shouldn't this function expect a python list of objects to then extract into std::string objects? Or are you using a library that handles that for you? – Kenny Ostrom Sep 20 '22 at 13:53
  • It takes the python module name so `foo.bar.module` and then a vector of strings to get to that variable, for example, for an enum, it could be `tempenum`, `shop`, `value`. – superman_565 Sep 20 '22 at 13:55

1 Answers1

1

Every call to PyObject_GetAttrString leaks a reference (excluding the final call, for which you return the reference). It returns a new reference so you need to call Py_DECREF on that reference.

You should also be error-checking your return values (most Python C API functions return NULL if they raise an exception). If you're getting a segmentation fault it's most likely because you're not error checking.

PyImport_AddModule seems pointless given that you just got a reference to the module when you imported it.

DavidW
  • 29,336
  • 6
  • 55
  • 86