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

C++封装Python模块读取TSV后调用PyImport_Import出现段错误

C++封装Python模块导入TSV数据后出现段错误的问题记录

我使用C++作为Python模块的封装层,先读取TSV文件转换为numpy数组,再导入Python模块将numpy数组传入做后续分析。最初使用随机生成的数组测试时程序运行正常,但将数组替换为TSV导入的内容后,调用PyImport_Import导入模块时出现段错误。

以下是相关代码:

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#define PY_SSIZE_T_CLEAN

#include <python3.8/Python.h>
#include "./venv/lib/python3.8/site-packages/numpy/core/include/numpy/arrayobject.h"

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <random>
#include <fstream>
#include <sstream>

int main(int argc, char* argv[]) {

    setenv("PYTHONPATH", ".", 0);

    Py_Initialize();
    import_array();

    static const int numberRows = 1000;
    static const int numberColumns = 500;

    npy_intp dims[2]{ numberRows, numberColumns };

    static const int numberDims = 2;

    double(*c_arr)[numberColumns]{ new double[numberRows][numberColumns] };

    // *********************************************************** 
    // 这部分代码生成随机数组,和其余代码搭配运行正常
    // // initialize random number generation
    // typedef std::mt19937 MyRNG;
    // std::random_device r;
    // MyRNG rng{r()};
    // std::lognormal_distribution<double> lognormalDistribution(1.6, 0.25);

    // //populate array
    // for (int i=0; i < numberRows; i++) {
    //     for (int j=0; j < numberColumns; j++) {
    //         c_arr[i][j] = lognormalDistribution(rng);
    //     }
    // }
    // ***********************************************************

    // *********************************************************** 
    // 这部分代码从TSV读取数组,导致代码在PyImport_Import处失败
    std::ifstream data("data.mat");
    std::string line;
    int row = 0;
    int column = 0;
    while (std::getline(data, line)) {
        std::stringstream lineStream(line);
        std::string cell;
        while (std::getline(lineStream, cell, '	')) {
            c_arr[row][column] = std::stod(cell);
            column++;
        }
        row++;
        column = 0;
        if (row > numberRows) {
            break;
        }
    }
    // *********************************************************** 

    PyArrayObject *npArray = reinterpret_cast<PyArrayObject*>(
        PyArray_SimpleNewFromData(numberDims, dims, NPY_DOUBLE, reinterpret_cast<void*>(c_arr))
        );

    const char *moduleName = "cpp_test";
    PyObject *pname = PyUnicode_FromString(moduleName);

    // ***********************************************************
    // 代码在此处失败 - 段错误
    PyObject *pyModule = PyImport_Import(pname);


    // .......
    // 后续还有其他代码未附上
}

问题原因与解决

最初无法复现问题逻辑:随机数组运行正常,TSV读取后就崩溃,而且崩溃点在导入模块的位置,和数组读取逻辑看似无关。
后续排查发现这是一个非常低级的错误:读取TSV的循环停止条件写为row > numberRows,当TSV文件行数超过预设的numberRows时,row会先自增到numberRows + 1才会触发break,导致c_arr[row]访问时越界写入,破坏了堆内存结构。内存被破坏后后续执行Python API调用时就触发了段错误。
将停止条件修改为row == numberRows后,程序运行完全正常。
这个问题可以作为常见低级错误的参考:内存越界的崩溃点不一定和越界操作的位置一致,写边界判断时要格外注意阈值条件的正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:54:04