2014-12-10 4 views
0

나는 C++에서 파이썬을 사용하려고하는데 다음 코드를 가지고있다. 필자는 사용자 입력 경로에서 sys.path.append를 구문 분석하고 수행하려고했습니다. PyRun_SimpleString에 대한 호출이 클래스의 private class var에 일종의 spillage를 일으킨 것처럼 보입니다. 어떻게 이런일이 일어 났습니까? 다양한 버퍼 크기 50, 150, 200을 시도했지만 출력을 변경하지 않았습니다.PyRun_SimpleString 호출로 인한 메모리 손상?

class Myclass 
{ 
    ... 
    private: 
     char *_modName; 
     char *_modDir; 
}; 
Myclass::Myclass() 
{ 
    Py_Initialize(); 
    PyRun_SimpleString("import sys"); 
    PyRun_SimpleString((char *)"sys.path.append('/home/userA/Python')"); 
} 
Myclass::init() 
{ 
    // this function is called before Myclass::test() 
    // a couple other python funcitons are called as listed below. 
    // PyString_FromString, PyImport_Import, PyObject_GetAttrString, PyTuple_New, PyTuple_SetItem, PyObject_CallObject, PyDict_GetItemString 
} 
Myclass::test() 
{ 
    char buffer[150]; 
    char *strP1 = (char *)"sys.path.append('"; 
    char *strP2 = (char *)"')"; 
    strcpy (buffer, strP1); 
    strcat (buffer, _modDir); 
    strcat (buffer, strP2); 
    printf("Before %s\n", _modDir); 
    printf("Before %s\n", _modName); 
    PyRun_SimpleString(buffer); 
    printf("After %s\n", _modName); 
} 

다음은 출력물입니다. 참고로 저는 일러스트레이션 목적으로 만 a, b, c, d, f를 사용하고 있습니다. PyRun_SimpleString (buffer)처럼 _modName에 버퍼의 끝을 채 웁니다.

Before /aaa/bbb/ccc/ddd 
Before ffffff 
After cc/ddd' 
+1

_modName은 어떻게 초기화됩니까? 초기화 된 메모리가 파이썬에서 자유롭게 재사용 될 수 있습니까? –

+0

C++을 사용하고 있으므로 'string'유형을 사용 하시길 권해 드릴까요? 오류가 발생하기 쉽고 버퍼 크기와 할당 해제에 대해 걱정할 필요가 없습니다. '(char *)'를 전달해야 할 때'string'에 내장 된'c_str()'메소드를 호출하면됩니다. – DaveS

+0

_modName은 python 스크립트의 return dict를 구문 분석 할 때 검색됩니다. _modName = PyString_AsString (PyDict_GetItemString (pValue, (char *) "modName"))); – elgnoh

답변

0

올바른 방향의 힌트를 주신 Klamer Schutte에게 감사드립니다. 내 코드의 DECRF가 범인입니다. 참조가 작동하는 방식과 비슷하지 않은 것 같습니다. DECREF 호출은 _modName이 가리키는 내용과 함께 pValue를 릴리스했습니다. _modName 할당 후에 Py_INCREF (pValue)를 추가해야합니까? 더 많은 초보자 quesiton이 될 것이라고 생각하십니까?

_modName = PyString_AsString (PyDict_GetItemString(pValue, (char*)"modName")); 
Py_DECREF(pValue);