2013-01-09 28 views
1

在下面的hello world C程序中,我既在擴展也在嵌入Python。單線程C程序中Py_Finalize(python 2.5)的Segfault

spam.c

#include <Python.h> 

static PyObject * 
spam_echo(PyObject *self, PyObject *args) { 
    const char *command; 
    int sts; 

    if (!PyArg_ParseTuple(args, "s", &command)) 
     return NULL; 
    sts = printf("%s\n", command); 
    return Py_BuildValue("i", sts); 
} 

static PyMethodDef SpamMethods[] = { 
    {"echo", spam_echo, METH_VARARGS, "Prints passed argument"}, 
    {NULL, NULL, 0, NULL} 
}; 

PyMODINIT_FUNC 
initspam(void) { 
    (void) Py_InitModule("spam", SpamMethods); 
} 

int main(int argc, char *argv[]) { 
    PyObject *args; 
    PyObject *arg; 
    PyObject *result; 
    PyObject *moduleName; 
    PyObject *module; 
    PyObject *func; 

    Py_SetProgramName(argv[0]); 
    Py_Initialize(); 
    initspam(); 

    PyRun_SimpleFile(fopen("foo.py", "r"), "foo.py"); 

    moduleName = PyString_FromString("__main__"); 
    module = PyImport_Import(moduleName); 
    Py_DECREF(moduleName); 
    if (!module) { 
     return 1; 
    } 

    func = PyObject_GetAttrString(module, "foo"); 
    Py_DECREF(module); 
    if (!func || !PyCallable_Check(func)) { 
     return 1; 
    } 

    args = PyTuple_New(1); 
    arg = Py_BuildValue("s", "hello world"); 
    PyTuple_SetItem(args, 0, arg); 

    result = PyObject_CallObject(func, args); 
    Py_DECREF(arg); 
    Py_DECREF(args); 
    Py_DECREF(func); 

    printf("== before\n"); 
    Py_Finalize(); 
    printf("== after\n"); 
} 

這裏是調用的Python程序:

foo.py

#!/usr/bin/python 

import spam 

def foo(cmd): 
    spam.echo(cmd) 

gcc spam.c -I/usr/include/python2.5/ -lpython2.5 
0123編譯

與GCC 4.2.4-1ubuntu4和我在Ubuntu Hardy上使用python2.5-dev軟件包。

基本上,我有在Py_Finalize段錯誤作爲顯示輸出:

hello world 
== before 
Segmentation fault 
+0

我其實剛剛發現了導致段錯誤的原因!我必須註釋掉'Py_DECREF(arg)'或'Py_DECREF(args)'。我的猜測是,減少'args'也會自動減少'arg',所以我會減少'arg'兩次。我仍然需要確認或其他人的解釋! –

回答

2

交換線路Py_DECREF(args);Py_DECREF(arg);解決問題。段錯誤是在Py_DECREF(args)已被釋放後訪問arg的結果。

+0

非常感謝!這有幫助! –