You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyObject_Print触发Segmentation fault的原因及解决方法

问题描述

在CPython扩展代码中调用PyObject_Print打印PyObject时触发Segmentation fault,但通过PyObject_Repr结合PyUnicode_AsUTF8再使用printf却能正常运行。更换多个Python版本(3.7、Anaconda 3.11、mingw64 3.10.10)并使用VSCode调试后,问题依然存在。

测试代码

int main(){
    Py_Initialize();
    ///////////////////////////////////////////
    PyObject *tmp1 = PyLong_FromLong((1<<29)*3);
    PyObject *tmp2 = PyLong_FromLong((1<<20)*41+1264);
    PyObject *u;
    u = PyNumber_Multiply(tmp1,tmp2);
    PyObject_Print(u,stdout,Py_PRINT_RAW); // Segmentation fault here

    const char* uu = PyUnicode_AsUTF8(PyObject_Repr(u));
    printf("%s\n", uu); // it works
    Py_Finalize();
    return 0;
}

编译配置(tasks.json)

{
    "type": "cppbuild",
    "label": "C/C++: gcc.exe build active file",
    "command": "C:\\msys64\\mingw64\\bin\\gcc.exe",
    "args": [
        "-fdiagnostics-color=always",
        "-g",
        "${file}",
        "-o",
        "${fileDirname}\\${fileBasenameNoExtension}.exe",
        "-I",
        "C:/Users/.../AppData/Local/Programs/Python/Python37/include",
        "-L",
        "C:/Users/.../AppData/Local/Programs/Python/Python37/libs",
        "-lpython37"
    ],
    "options": {
        "cwd": "${fileDirname}"
    },
    "problemMatcher": [
        "$gcc"
    ],
    "group": {
        "kind": "build",
        "isDefault": true
    },
    "detail": "Task generated by Debugger."
}

不同版本错误细节:Python3.10.10调试时错误为Thread 1 received signal SIGSEGV, Segmentation fault. ntdll!TpWorkOnBehalfClearTicket () from C:\\WINDOWS\\SYSTEM32\\ntdll.dll,与Python3.7的错误细节不同。


解决方案
  • 改用Python原生stdout对象:Windows环境下,mingw编译的C程序与MSVC编译的Python(如官方3.7版本)的FILE*结构存在兼容性差异,直接传递C的stdout给PyObject_Print会导致段错误。替换为Python自身的sys.stdout对象:

    int main(){
        Py_Initialize();
        // 初始化并获取Python的sys.stdout
        PyObject *sys_module = PyImport_ImportModule("sys");
        PyObject *stdout_obj = PyObject_GetAttrString(sys_module, "stdout");
    
        PyObject *tmp1 = PyLong_FromLong((1<<29)*3);
        PyObject *tmp2 = PyLong_FromLong((1<<20)*41+1264);
        PyObject *u = PyNumber_Multiply(tmp1, tmp2);
    
        // 使用Python的stdout对象调用PyObject_Print
        PyObject_Print(u, stdout_obj, Py_PRINT_RAW);
        printf("\n"); // 手动换行,避免输出粘连
    
        const char* uu = PyUnicode_AsUTF8(PyObject_Repr(u));
        printf("%s\n", uu);
    
        // 释放引用计数
        Py_DECREF(u);
        Py_DECREF(tmp1);
        Py_DECREF(tmp2);
        Py_DECREF(stdout_obj);
        Py_DECREF(sys_module);
    
        Py_Finalize();
        return 0;
    }
    
  • 保持编译环境一致性:如果用mingw编译C代码,优先使用mingw编译的Python版本(如你尝试的3.10.10),避免混合MSVC和mingw编译的二进制文件,减少底层兼容性问题。

  • 强制检查API返回值:虽然当前场景下u有效,但养成检查每个Python API返回值的习惯能提前规避错误,比如:

    if (!tmp1 || !tmp2) {
        // 处理内存分配或对象创建失败
        Py_Finalize();
        return 1;
    }
    u = PyNumber_Multiply(tmp1, tmp2);
    if (!u) {
        // 处理乘法操作失败
        Py_DECREF(tmp1);
        Py_DECREF(tmp2);
        Py_Finalize();
        return 1;
    }
    

内容的提问来源于stack exchange,提问作者Jun Hong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 05:02:17