python wrapper crashed which call Python from C++












0














I have a project which need to call Python scripts from C++, because I have many objects which need to call Python, so I write a common class; which like the below:



  PythonTunerIntf * PythonTunerIntf::instance()
{
if (instance_ == nullptr)
{
instance_ = new PythonTunerIntf();
}
return instance_;
}

void PythonTunerIntf::release()
{
if (instance_)
{
delete instance_;
instance_ = nullptr;
}
}

//the below function is used to get the path accessable from python interpretor
void PythonTunerIntf::append_path(std::string path)
{
PyObject* sysPath = PySys_GetObject((char*)"path");
PyObject* curDir = PyUnicode_FromString(path.c_str());
PyList_Append(sysPath, curDir);
Py_DECREF(curDir);
}

//import the module from the path
void PythonTunerIntf::append_file(std::string file_name)
{
PyObject* pName = PyUnicode_FromString(file_name.c_str());
pModule = PyImport_Import(pName);
Py_DECREF(pName);
//assert(pModule != nullptr);
if (pModule == nullptr)
{
printf("not able to load python script %sn", file_name.c_str());
PyErr_Print();
}
}


//the below two functions set the needed parameters from C++
void PythonTunerIntf::append_item(std::string key, Python_Intf_Args val)
{
m_values.push_back(std::make_pair(key, val));
}

void PythonTunerIntf::buildValues()
{
for (auto val : m_values)
{
PyObject* param_key = Py_BuildValue("s", val.first.c_str());
PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? Py_BuildValue("i", val.second.int_arg)
: Py_BuildValue("s", val.second.str_arg.c_str());
PyDict_SetItem(pFunc_params, param_key, param_val);
Py_DECREF(param_key);
Py_DECREF(param_val);
}
}

//get started to call python, and read the returned values to C++
std::vector<std::pair<std::string, float> > PythonTunerIntf::call_func(std::string func_name)
{
std::vector<std::pair<std::string, float> > returned_data;
pFunc = PyObject_GetAttrString(pModule, func_name.c_str());
Py_DECREF(pModule);
if (pFunc && PyCallable_Check(pFunc))
{
PyObject* returned_item = PyObject_CallFunctionObjArgs(pFunc, pFunc_params, NULL);
Py_DECREF(pFunc);
Py_DECREF(pFunc_params);
assert(returned_item != nullptr);
assert(PyDict_Check(returned_item));
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(returned_item, &pos, &key, &value))
{
assert(PyUnicode_Check(key));
if (PyFloat_Check(value))
{
double result_value{ PyFloat_AsDouble(value) };
float result = static_cast<float>(result_value);
ssize_t size{ PyUnicode_GetSize(key) };
wchar_t *wstr = (wchar_t*)malloc(sizeof(wchar_t) * size);
PyUnicode_AsWideChar(key, wstr, size);
std::wstring wide(wstr, size);
std::string result_key{ wide.begin(), wide.end() };
returned_data.emplace_back(std::make_pair(result_key, result_value));
free(wstr);
}
else if (PyLong_Check(value))
{
long result_value{ PyLong_AsLong(value) };
float result = static_cast<float>(result_value);
ssize_t size{ PyUnicode_GetSize(key) };
wchar_t *wstr = (wchar_t*)malloc(sizeof(wchar_t) * size);
PyUnicode_AsWideChar(key, wstr, size);
std::wstring wide(wstr, size);
std::string result_key{ wide.begin(), wide.end() };
returned_data.emplace_back(std::make_pair(result_key, result_value));
free(wstr);
}
Py_DECREF(key);
Py_DECREF(value);
}
Py_DECREF(returned_item);
PyDict_Clear(pFunc_params);
}
m_values.clear();
return returned_data;
}


PythonTunerIntf::~PythonTunerIntf()
{
Py_XDECREF(pFunc_params);
Py_Finalize();
}



PythonTunerIntf::PythonTunerIntf()
{
Py_Initialize();
if (!Py_IsInitialized())
{
std::runtime_error("canot initialize Python interpreter");
}
pFunc_params = PyDict_New();
assert(pFunc_params != nullptr);

pModule = nullptr;
pFunc = nullptr;
}


When I call this class's instance the second time, will crash, the message in visual studio gives "Exception thrown: read access violation.
bp was 0xFFFFFFFFFFFFFFFF."



the call stack is



python36.dll!_PyObject_Alloc(int use_calloc, void * nelem, unsigned __int64 elsize, unsigned __int64) Line 1258 C
python36.dll!parsetok(tok_state * tok, grammar * g, int start, perrdetail * err_ret, int * flags) Line 229 C
python36.dll!PyParser_ParseStringObject(const char * s, _object * filename, grammar * g, int start, perrdetail * err_ret, int * flags) Line 68 C
python36.dll!PyParser_ASTFromStringObject(const char * s, _object * filename, int start, PyCompilerFlags * flags, _arena * arena) Line 1118 C
python36.dll!Py_CompileStringObject(const char * str, _object * filename, int start, PyCompilerFlags * flags, int optimize) Line 1033 C
python36.dll!builtin_compile_impl(_object * source, _object * filename, _object * mode, const char * flags, int dont_inherit, int optimize, int) Line 774 C
python36.dll!builtin_compile(_object * module, _object * * args, __int64 nargs, _object * kwnames) Line 175 C
python36.dll!_PyCFunction_FastCallDict(_object * func_obj, _object * * args, __int64 nargs, _object * kwargs) Line 250 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3377 C
python36.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * * args, __int64 argcount, _object * * kwnames, _object * * kwargs, __int64 kwcount, int kwstep, _object * * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4139 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3313 C
python36.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * * args, __int64 argcount, _object * * kwnames, _object * * kwargs, __int64 kwcount, int kwstep, _object * * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4139 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!_PyFunction_FastCallDict(_object * func, _object * * args, __int64 nargs, _object * kwargs) Line 4993 C
python36.dll!_PyObject_FastCallDict(_object * func, _object * * args, __int64 nargs, _object * kwargs) Line 2296 C
python36.dll!_PyObject_CallMethodIdObjArgs(_object * callable, _Py_Identifier * name, ...) Line 2782 C
python36.dll!PyImport_ImportModuleLevelObject(_object * name, _object * globals, _object * locals, _object * fromlist, int level) Line 1592 C
python36.dll!builtin___import__(_object * self, _object * args, _object * kwds) Line 233 C
python36.dll!PyCFunction_Call(_object * func, _object * args, _object * kwds) Line 99 C
python36.dll!PyObject_Call(_object * func, _object * args, _object * kwargs) Line 2246 C
python36.dll!call_function_tail(_object * callable, _object * args) Line 2501 C
python36.dll!PyObject_CallFunction(_object * callable, const char * format, ...) Line 2525 C
python36.dll!PyImport_Import(_object * module_name) Line 1781 C


Any suggestions on the PythonTunerIntf class implementation? I don't which part will have memory leakage.










share|improve this question






















  • For this code PyObject* param_key = Py_BuildValue("s", val.first.c_str()); PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? (Py_BuildValue("i", val.second.int_arg)) : (Py_BuildValue("s", val.second.str_arg.c_str())); when goes to param_key, the param_key's ob_refcnt = 1, this should be correct, but when executed the second line, the ob_refcnt = 408 for param_val; why the refcnt is so large for param_val variable.
    – yewei
    Nov 12 at 7:41


















0














I have a project which need to call Python scripts from C++, because I have many objects which need to call Python, so I write a common class; which like the below:



  PythonTunerIntf * PythonTunerIntf::instance()
{
if (instance_ == nullptr)
{
instance_ = new PythonTunerIntf();
}
return instance_;
}

void PythonTunerIntf::release()
{
if (instance_)
{
delete instance_;
instance_ = nullptr;
}
}

//the below function is used to get the path accessable from python interpretor
void PythonTunerIntf::append_path(std::string path)
{
PyObject* sysPath = PySys_GetObject((char*)"path");
PyObject* curDir = PyUnicode_FromString(path.c_str());
PyList_Append(sysPath, curDir);
Py_DECREF(curDir);
}

//import the module from the path
void PythonTunerIntf::append_file(std::string file_name)
{
PyObject* pName = PyUnicode_FromString(file_name.c_str());
pModule = PyImport_Import(pName);
Py_DECREF(pName);
//assert(pModule != nullptr);
if (pModule == nullptr)
{
printf("not able to load python script %sn", file_name.c_str());
PyErr_Print();
}
}


//the below two functions set the needed parameters from C++
void PythonTunerIntf::append_item(std::string key, Python_Intf_Args val)
{
m_values.push_back(std::make_pair(key, val));
}

void PythonTunerIntf::buildValues()
{
for (auto val : m_values)
{
PyObject* param_key = Py_BuildValue("s", val.first.c_str());
PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? Py_BuildValue("i", val.second.int_arg)
: Py_BuildValue("s", val.second.str_arg.c_str());
PyDict_SetItem(pFunc_params, param_key, param_val);
Py_DECREF(param_key);
Py_DECREF(param_val);
}
}

//get started to call python, and read the returned values to C++
std::vector<std::pair<std::string, float> > PythonTunerIntf::call_func(std::string func_name)
{
std::vector<std::pair<std::string, float> > returned_data;
pFunc = PyObject_GetAttrString(pModule, func_name.c_str());
Py_DECREF(pModule);
if (pFunc && PyCallable_Check(pFunc))
{
PyObject* returned_item = PyObject_CallFunctionObjArgs(pFunc, pFunc_params, NULL);
Py_DECREF(pFunc);
Py_DECREF(pFunc_params);
assert(returned_item != nullptr);
assert(PyDict_Check(returned_item));
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(returned_item, &pos, &key, &value))
{
assert(PyUnicode_Check(key));
if (PyFloat_Check(value))
{
double result_value{ PyFloat_AsDouble(value) };
float result = static_cast<float>(result_value);
ssize_t size{ PyUnicode_GetSize(key) };
wchar_t *wstr = (wchar_t*)malloc(sizeof(wchar_t) * size);
PyUnicode_AsWideChar(key, wstr, size);
std::wstring wide(wstr, size);
std::string result_key{ wide.begin(), wide.end() };
returned_data.emplace_back(std::make_pair(result_key, result_value));
free(wstr);
}
else if (PyLong_Check(value))
{
long result_value{ PyLong_AsLong(value) };
float result = static_cast<float>(result_value);
ssize_t size{ PyUnicode_GetSize(key) };
wchar_t *wstr = (wchar_t*)malloc(sizeof(wchar_t) * size);
PyUnicode_AsWideChar(key, wstr, size);
std::wstring wide(wstr, size);
std::string result_key{ wide.begin(), wide.end() };
returned_data.emplace_back(std::make_pair(result_key, result_value));
free(wstr);
}
Py_DECREF(key);
Py_DECREF(value);
}
Py_DECREF(returned_item);
PyDict_Clear(pFunc_params);
}
m_values.clear();
return returned_data;
}


PythonTunerIntf::~PythonTunerIntf()
{
Py_XDECREF(pFunc_params);
Py_Finalize();
}



PythonTunerIntf::PythonTunerIntf()
{
Py_Initialize();
if (!Py_IsInitialized())
{
std::runtime_error("canot initialize Python interpreter");
}
pFunc_params = PyDict_New();
assert(pFunc_params != nullptr);

pModule = nullptr;
pFunc = nullptr;
}


When I call this class's instance the second time, will crash, the message in visual studio gives "Exception thrown: read access violation.
bp was 0xFFFFFFFFFFFFFFFF."



the call stack is



python36.dll!_PyObject_Alloc(int use_calloc, void * nelem, unsigned __int64 elsize, unsigned __int64) Line 1258 C
python36.dll!parsetok(tok_state * tok, grammar * g, int start, perrdetail * err_ret, int * flags) Line 229 C
python36.dll!PyParser_ParseStringObject(const char * s, _object * filename, grammar * g, int start, perrdetail * err_ret, int * flags) Line 68 C
python36.dll!PyParser_ASTFromStringObject(const char * s, _object * filename, int start, PyCompilerFlags * flags, _arena * arena) Line 1118 C
python36.dll!Py_CompileStringObject(const char * str, _object * filename, int start, PyCompilerFlags * flags, int optimize) Line 1033 C
python36.dll!builtin_compile_impl(_object * source, _object * filename, _object * mode, const char * flags, int dont_inherit, int optimize, int) Line 774 C
python36.dll!builtin_compile(_object * module, _object * * args, __int64 nargs, _object * kwnames) Line 175 C
python36.dll!_PyCFunction_FastCallDict(_object * func_obj, _object * * args, __int64 nargs, _object * kwargs) Line 250 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3377 C
python36.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * * args, __int64 argcount, _object * * kwnames, _object * * kwargs, __int64 kwcount, int kwstep, _object * * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4139 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3313 C
python36.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * * args, __int64 argcount, _object * * kwnames, _object * * kwargs, __int64 kwcount, int kwstep, _object * * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4139 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!_PyFunction_FastCallDict(_object * func, _object * * args, __int64 nargs, _object * kwargs) Line 4993 C
python36.dll!_PyObject_FastCallDict(_object * func, _object * * args, __int64 nargs, _object * kwargs) Line 2296 C
python36.dll!_PyObject_CallMethodIdObjArgs(_object * callable, _Py_Identifier * name, ...) Line 2782 C
python36.dll!PyImport_ImportModuleLevelObject(_object * name, _object * globals, _object * locals, _object * fromlist, int level) Line 1592 C
python36.dll!builtin___import__(_object * self, _object * args, _object * kwds) Line 233 C
python36.dll!PyCFunction_Call(_object * func, _object * args, _object * kwds) Line 99 C
python36.dll!PyObject_Call(_object * func, _object * args, _object * kwargs) Line 2246 C
python36.dll!call_function_tail(_object * callable, _object * args) Line 2501 C
python36.dll!PyObject_CallFunction(_object * callable, const char * format, ...) Line 2525 C
python36.dll!PyImport_Import(_object * module_name) Line 1781 C


Any suggestions on the PythonTunerIntf class implementation? I don't which part will have memory leakage.










share|improve this question






















  • For this code PyObject* param_key = Py_BuildValue("s", val.first.c_str()); PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? (Py_BuildValue("i", val.second.int_arg)) : (Py_BuildValue("s", val.second.str_arg.c_str())); when goes to param_key, the param_key's ob_refcnt = 1, this should be correct, but when executed the second line, the ob_refcnt = 408 for param_val; why the refcnt is so large for param_val variable.
    – yewei
    Nov 12 at 7:41
















0












0








0







I have a project which need to call Python scripts from C++, because I have many objects which need to call Python, so I write a common class; which like the below:



  PythonTunerIntf * PythonTunerIntf::instance()
{
if (instance_ == nullptr)
{
instance_ = new PythonTunerIntf();
}
return instance_;
}

void PythonTunerIntf::release()
{
if (instance_)
{
delete instance_;
instance_ = nullptr;
}
}

//the below function is used to get the path accessable from python interpretor
void PythonTunerIntf::append_path(std::string path)
{
PyObject* sysPath = PySys_GetObject((char*)"path");
PyObject* curDir = PyUnicode_FromString(path.c_str());
PyList_Append(sysPath, curDir);
Py_DECREF(curDir);
}

//import the module from the path
void PythonTunerIntf::append_file(std::string file_name)
{
PyObject* pName = PyUnicode_FromString(file_name.c_str());
pModule = PyImport_Import(pName);
Py_DECREF(pName);
//assert(pModule != nullptr);
if (pModule == nullptr)
{
printf("not able to load python script %sn", file_name.c_str());
PyErr_Print();
}
}


//the below two functions set the needed parameters from C++
void PythonTunerIntf::append_item(std::string key, Python_Intf_Args val)
{
m_values.push_back(std::make_pair(key, val));
}

void PythonTunerIntf::buildValues()
{
for (auto val : m_values)
{
PyObject* param_key = Py_BuildValue("s", val.first.c_str());
PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? Py_BuildValue("i", val.second.int_arg)
: Py_BuildValue("s", val.second.str_arg.c_str());
PyDict_SetItem(pFunc_params, param_key, param_val);
Py_DECREF(param_key);
Py_DECREF(param_val);
}
}

//get started to call python, and read the returned values to C++
std::vector<std::pair<std::string, float> > PythonTunerIntf::call_func(std::string func_name)
{
std::vector<std::pair<std::string, float> > returned_data;
pFunc = PyObject_GetAttrString(pModule, func_name.c_str());
Py_DECREF(pModule);
if (pFunc && PyCallable_Check(pFunc))
{
PyObject* returned_item = PyObject_CallFunctionObjArgs(pFunc, pFunc_params, NULL);
Py_DECREF(pFunc);
Py_DECREF(pFunc_params);
assert(returned_item != nullptr);
assert(PyDict_Check(returned_item));
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(returned_item, &pos, &key, &value))
{
assert(PyUnicode_Check(key));
if (PyFloat_Check(value))
{
double result_value{ PyFloat_AsDouble(value) };
float result = static_cast<float>(result_value);
ssize_t size{ PyUnicode_GetSize(key) };
wchar_t *wstr = (wchar_t*)malloc(sizeof(wchar_t) * size);
PyUnicode_AsWideChar(key, wstr, size);
std::wstring wide(wstr, size);
std::string result_key{ wide.begin(), wide.end() };
returned_data.emplace_back(std::make_pair(result_key, result_value));
free(wstr);
}
else if (PyLong_Check(value))
{
long result_value{ PyLong_AsLong(value) };
float result = static_cast<float>(result_value);
ssize_t size{ PyUnicode_GetSize(key) };
wchar_t *wstr = (wchar_t*)malloc(sizeof(wchar_t) * size);
PyUnicode_AsWideChar(key, wstr, size);
std::wstring wide(wstr, size);
std::string result_key{ wide.begin(), wide.end() };
returned_data.emplace_back(std::make_pair(result_key, result_value));
free(wstr);
}
Py_DECREF(key);
Py_DECREF(value);
}
Py_DECREF(returned_item);
PyDict_Clear(pFunc_params);
}
m_values.clear();
return returned_data;
}


PythonTunerIntf::~PythonTunerIntf()
{
Py_XDECREF(pFunc_params);
Py_Finalize();
}



PythonTunerIntf::PythonTunerIntf()
{
Py_Initialize();
if (!Py_IsInitialized())
{
std::runtime_error("canot initialize Python interpreter");
}
pFunc_params = PyDict_New();
assert(pFunc_params != nullptr);

pModule = nullptr;
pFunc = nullptr;
}


When I call this class's instance the second time, will crash, the message in visual studio gives "Exception thrown: read access violation.
bp was 0xFFFFFFFFFFFFFFFF."



the call stack is



python36.dll!_PyObject_Alloc(int use_calloc, void * nelem, unsigned __int64 elsize, unsigned __int64) Line 1258 C
python36.dll!parsetok(tok_state * tok, grammar * g, int start, perrdetail * err_ret, int * flags) Line 229 C
python36.dll!PyParser_ParseStringObject(const char * s, _object * filename, grammar * g, int start, perrdetail * err_ret, int * flags) Line 68 C
python36.dll!PyParser_ASTFromStringObject(const char * s, _object * filename, int start, PyCompilerFlags * flags, _arena * arena) Line 1118 C
python36.dll!Py_CompileStringObject(const char * str, _object * filename, int start, PyCompilerFlags * flags, int optimize) Line 1033 C
python36.dll!builtin_compile_impl(_object * source, _object * filename, _object * mode, const char * flags, int dont_inherit, int optimize, int) Line 774 C
python36.dll!builtin_compile(_object * module, _object * * args, __int64 nargs, _object * kwnames) Line 175 C
python36.dll!_PyCFunction_FastCallDict(_object * func_obj, _object * * args, __int64 nargs, _object * kwargs) Line 250 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3377 C
python36.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * * args, __int64 argcount, _object * * kwnames, _object * * kwargs, __int64 kwcount, int kwstep, _object * * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4139 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3313 C
python36.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * * args, __int64 argcount, _object * * kwnames, _object * * kwargs, __int64 kwcount, int kwstep, _object * * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4139 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!_PyFunction_FastCallDict(_object * func, _object * * args, __int64 nargs, _object * kwargs) Line 4993 C
python36.dll!_PyObject_FastCallDict(_object * func, _object * * args, __int64 nargs, _object * kwargs) Line 2296 C
python36.dll!_PyObject_CallMethodIdObjArgs(_object * callable, _Py_Identifier * name, ...) Line 2782 C
python36.dll!PyImport_ImportModuleLevelObject(_object * name, _object * globals, _object * locals, _object * fromlist, int level) Line 1592 C
python36.dll!builtin___import__(_object * self, _object * args, _object * kwds) Line 233 C
python36.dll!PyCFunction_Call(_object * func, _object * args, _object * kwds) Line 99 C
python36.dll!PyObject_Call(_object * func, _object * args, _object * kwargs) Line 2246 C
python36.dll!call_function_tail(_object * callable, _object * args) Line 2501 C
python36.dll!PyObject_CallFunction(_object * callable, const char * format, ...) Line 2525 C
python36.dll!PyImport_Import(_object * module_name) Line 1781 C


Any suggestions on the PythonTunerIntf class implementation? I don't which part will have memory leakage.










share|improve this question













I have a project which need to call Python scripts from C++, because I have many objects which need to call Python, so I write a common class; which like the below:



  PythonTunerIntf * PythonTunerIntf::instance()
{
if (instance_ == nullptr)
{
instance_ = new PythonTunerIntf();
}
return instance_;
}

void PythonTunerIntf::release()
{
if (instance_)
{
delete instance_;
instance_ = nullptr;
}
}

//the below function is used to get the path accessable from python interpretor
void PythonTunerIntf::append_path(std::string path)
{
PyObject* sysPath = PySys_GetObject((char*)"path");
PyObject* curDir = PyUnicode_FromString(path.c_str());
PyList_Append(sysPath, curDir);
Py_DECREF(curDir);
}

//import the module from the path
void PythonTunerIntf::append_file(std::string file_name)
{
PyObject* pName = PyUnicode_FromString(file_name.c_str());
pModule = PyImport_Import(pName);
Py_DECREF(pName);
//assert(pModule != nullptr);
if (pModule == nullptr)
{
printf("not able to load python script %sn", file_name.c_str());
PyErr_Print();
}
}


//the below two functions set the needed parameters from C++
void PythonTunerIntf::append_item(std::string key, Python_Intf_Args val)
{
m_values.push_back(std::make_pair(key, val));
}

void PythonTunerIntf::buildValues()
{
for (auto val : m_values)
{
PyObject* param_key = Py_BuildValue("s", val.first.c_str());
PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? Py_BuildValue("i", val.second.int_arg)
: Py_BuildValue("s", val.second.str_arg.c_str());
PyDict_SetItem(pFunc_params, param_key, param_val);
Py_DECREF(param_key);
Py_DECREF(param_val);
}
}

//get started to call python, and read the returned values to C++
std::vector<std::pair<std::string, float> > PythonTunerIntf::call_func(std::string func_name)
{
std::vector<std::pair<std::string, float> > returned_data;
pFunc = PyObject_GetAttrString(pModule, func_name.c_str());
Py_DECREF(pModule);
if (pFunc && PyCallable_Check(pFunc))
{
PyObject* returned_item = PyObject_CallFunctionObjArgs(pFunc, pFunc_params, NULL);
Py_DECREF(pFunc);
Py_DECREF(pFunc_params);
assert(returned_item != nullptr);
assert(PyDict_Check(returned_item));
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(returned_item, &pos, &key, &value))
{
assert(PyUnicode_Check(key));
if (PyFloat_Check(value))
{
double result_value{ PyFloat_AsDouble(value) };
float result = static_cast<float>(result_value);
ssize_t size{ PyUnicode_GetSize(key) };
wchar_t *wstr = (wchar_t*)malloc(sizeof(wchar_t) * size);
PyUnicode_AsWideChar(key, wstr, size);
std::wstring wide(wstr, size);
std::string result_key{ wide.begin(), wide.end() };
returned_data.emplace_back(std::make_pair(result_key, result_value));
free(wstr);
}
else if (PyLong_Check(value))
{
long result_value{ PyLong_AsLong(value) };
float result = static_cast<float>(result_value);
ssize_t size{ PyUnicode_GetSize(key) };
wchar_t *wstr = (wchar_t*)malloc(sizeof(wchar_t) * size);
PyUnicode_AsWideChar(key, wstr, size);
std::wstring wide(wstr, size);
std::string result_key{ wide.begin(), wide.end() };
returned_data.emplace_back(std::make_pair(result_key, result_value));
free(wstr);
}
Py_DECREF(key);
Py_DECREF(value);
}
Py_DECREF(returned_item);
PyDict_Clear(pFunc_params);
}
m_values.clear();
return returned_data;
}


PythonTunerIntf::~PythonTunerIntf()
{
Py_XDECREF(pFunc_params);
Py_Finalize();
}



PythonTunerIntf::PythonTunerIntf()
{
Py_Initialize();
if (!Py_IsInitialized())
{
std::runtime_error("canot initialize Python interpreter");
}
pFunc_params = PyDict_New();
assert(pFunc_params != nullptr);

pModule = nullptr;
pFunc = nullptr;
}


When I call this class's instance the second time, will crash, the message in visual studio gives "Exception thrown: read access violation.
bp was 0xFFFFFFFFFFFFFFFF."



the call stack is



python36.dll!_PyObject_Alloc(int use_calloc, void * nelem, unsigned __int64 elsize, unsigned __int64) Line 1258 C
python36.dll!parsetok(tok_state * tok, grammar * g, int start, perrdetail * err_ret, int * flags) Line 229 C
python36.dll!PyParser_ParseStringObject(const char * s, _object * filename, grammar * g, int start, perrdetail * err_ret, int * flags) Line 68 C
python36.dll!PyParser_ASTFromStringObject(const char * s, _object * filename, int start, PyCompilerFlags * flags, _arena * arena) Line 1118 C
python36.dll!Py_CompileStringObject(const char * str, _object * filename, int start, PyCompilerFlags * flags, int optimize) Line 1033 C
python36.dll!builtin_compile_impl(_object * source, _object * filename, _object * mode, const char * flags, int dont_inherit, int optimize, int) Line 774 C
python36.dll!builtin_compile(_object * module, _object * * args, __int64 nargs, _object * kwnames) Line 175 C
python36.dll!_PyCFunction_FastCallDict(_object * func_obj, _object * * args, __int64 nargs, _object * kwargs) Line 250 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3377 C
python36.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * * args, __int64 argcount, _object * * kwnames, _object * * kwargs, __int64 kwcount, int kwstep, _object * * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4139 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3313 C
python36.dll!_PyEval_EvalCodeWithName(_object * _co, _object * globals, _object * locals, _object * * args, __int64 argcount, _object * * kwnames, _object * * kwargs, __int64 kwcount, int kwstep, _object * * defs, __int64 defcount, _object * kwdefs, _object * closure, _object * name, _object * qualname) Line 4139 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!call_function(_object * * * pp_stack, __int64 oparg, _object * kwnames) Line 4830 C
python36.dll!_PyEval_EvalFrameDefault(_frame * f, int throwflag) Line 3297 C
python36.dll!_PyFunction_FastCallDict(_object * func, _object * * args, __int64 nargs, _object * kwargs) Line 4993 C
python36.dll!_PyObject_FastCallDict(_object * func, _object * * args, __int64 nargs, _object * kwargs) Line 2296 C
python36.dll!_PyObject_CallMethodIdObjArgs(_object * callable, _Py_Identifier * name, ...) Line 2782 C
python36.dll!PyImport_ImportModuleLevelObject(_object * name, _object * globals, _object * locals, _object * fromlist, int level) Line 1592 C
python36.dll!builtin___import__(_object * self, _object * args, _object * kwds) Line 233 C
python36.dll!PyCFunction_Call(_object * func, _object * args, _object * kwds) Line 99 C
python36.dll!PyObject_Call(_object * func, _object * args, _object * kwargs) Line 2246 C
python36.dll!call_function_tail(_object * callable, _object * args) Line 2501 C
python36.dll!PyObject_CallFunction(_object * callable, const char * format, ...) Line 2525 C
python36.dll!PyImport_Import(_object * module_name) Line 1781 C


Any suggestions on the PythonTunerIntf class implementation? I don't which part will have memory leakage.







python c++






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 at 3:11









yewei

5319




5319












  • For this code PyObject* param_key = Py_BuildValue("s", val.first.c_str()); PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? (Py_BuildValue("i", val.second.int_arg)) : (Py_BuildValue("s", val.second.str_arg.c_str())); when goes to param_key, the param_key's ob_refcnt = 1, this should be correct, but when executed the second line, the ob_refcnt = 408 for param_val; why the refcnt is so large for param_val variable.
    – yewei
    Nov 12 at 7:41




















  • For this code PyObject* param_key = Py_BuildValue("s", val.first.c_str()); PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? (Py_BuildValue("i", val.second.int_arg)) : (Py_BuildValue("s", val.second.str_arg.c_str())); when goes to param_key, the param_key's ob_refcnt = 1, this should be correct, but when executed the second line, the ob_refcnt = 408 for param_val; why the refcnt is so large for param_val variable.
    – yewei
    Nov 12 at 7:41


















For this code PyObject* param_key = Py_BuildValue("s", val.first.c_str()); PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? (Py_BuildValue("i", val.second.int_arg)) : (Py_BuildValue("s", val.second.str_arg.c_str())); when goes to param_key, the param_key's ob_refcnt = 1, this should be correct, but when executed the second line, the ob_refcnt = 408 for param_val; why the refcnt is so large for param_val variable.
– yewei
Nov 12 at 7:41






For this code PyObject* param_key = Py_BuildValue("s", val.first.c_str()); PyObject* param_val = (val.second.type == Python_Intf_Args::INT) ? (Py_BuildValue("i", val.second.int_arg)) : (Py_BuildValue("s", val.second.str_arg.c_str())); when goes to param_key, the param_key's ob_refcnt = 1, this should be correct, but when executed the second line, the ob_refcnt = 408 for param_val; why the refcnt is so large for param_val variable.
– yewei
Nov 12 at 7:41



















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255499%2fpython-wrapper-crashed-which-call-python-from-c%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255499%2fpython-wrapper-crashed-which-call-python-from-c%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Florida Star v. B. J. F.

Error while running script in elastic search , gateway timeout

Adding quotations to stringified JSON object values