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

Python C API调用sys.getsizeof()出现段错误,请求排查问题

问题分析与修正方案

核心错误点

  • 错误使用PyModule_New导入模块
    PyModule_New是用来创建全新的空模块对象,而非导入Python已有的sys模块。你用这个函数得到的sys对象根本没有getsizeof方法,后续调用PyObject_CallMethodObjArgs会返回NULL,直接访问这个空指针就会触发段错误。正确导入现有模块应该用PyImport_ImportModule("sys")。

  • 冗余的引用计数操作
    传入的obj参数在调用函数时应该已经持有合法的引用计数,额外执行Py_INCREF(obj)后又在结尾Py_DECREF(obj),会导致引用计数多减一次,可能引发对象提前释放或内存错误,直接去掉这两个操作即可。

  • 未检查API调用的返回值
    导入模块、获取方法、调用方法等步骤都可能失败返回NULL,你没有做任何错误检查就直接使用返回值,空指针访问必然触发段错误。

  • 冗余的字符串对象创建
    Py_BuildValue("s", "getsizeof")可以用更简洁的PyObject_GetAttrString替代,直接从sys模块获取getsizeof方法,省去手动创建字符串对象的步骤。


修正后的代码

// Returns in bytes the size of obj in memory (emulates sys.getsizeof(obj))
size_t getSizeOf(PyObject* obj) {
    // 检查输入对象合法性
    if (!obj) {
        return 0;
    }

    // 正确导入sys模块
    PyObject* sys_module = PyImport_ImportModule("sys");
    if (!sys_module) {
        PyErr_Print();
        return 0;
    }

    // 获取sys.getsizeof方法
    PyObject* getsizeof_func = PyObject_GetAttrString(sys_module, "getsizeof");
    Py_DECREF(sys_module); // 模块引用可提前释放
    if (!getsizeof_func || !PyCallable_Check(getsizeof_func)) {
        if (getsizeof_func) Py_DECREF(getsizeof_func);
        PyErr_Print();
        return 0;
    }

    // 调用getsizeof(obj)
    PyObject* result = PyObject_CallFunctionObjArgs(getsizeof_func, obj, NULL);
    Py_DECREF(getsizeof_func);
    if (!result) {
        PyErr_Print();
        return 0;
    }

    // 转换为size_t类型并合法性校验
    long tmp = PyLong_AsLong(result);
    size_t size = (tmp >= 0) ? (size_t)tmp : 0;
    Py_DECREF(result);

    return size;
}

修正说明

  1. 用PyImport_ImportModule正确导入sys模块
  2. 增加了所有关键步骤的错误检查,避免空指针访问
  3. 移除了不必要的引用计数操作,避免内存错误
  4. 使用PyObject_GetAttrString简化方法获取流程
  5. 对返回的长整型值做合法性判断,避免负数转换问题

内容的提问来源于stack exchange,提问作者TCA 166

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:40:30