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

使用PLplot绘制颜色图时触发Segmentation Fault错误求助

Segmentation Fault排查与修复:PLplot颜色图绘制程序

核心错误原因及修复

1. 主函数语法错误

主函数中存在无效代码Here is where the error pops up,会导致编译失败,直接删除该行即可。

2. 未检查数据是否为空

createColourMap函数直接访问data[0].size(),若readData返回空数据(如文件不存在、文件为空),data.size() == 0时data[0]会触发数组越界,引发segfault。

修复:
在使用数据前添加空校验:

void createColourMap(const std::vector<std::vector<int> >& data)
{
    if (data.empty()) {
        std::cerr << "Error: No data to plot." << std::endl;
        return;
    }
    int rows = data.size();
    int col = data[0].size();
    // 后续代码
}

3. 二维数组z索引越界

代码中z按列数分配指针数组PLFLT **z = new PLFLT*[col];,但赋值时使用z[i][j] = data[i][j],i的范围是0到col-1,而data的行数为rows,当col > rows时,data[i]会访问超出data的行范围,触发越界。

修复:
z的结构需匹配data的行优先结构:

// 按行数分配z的指针数组
PLFLT **z = new PLFLT*[rows];
for (int i = 0; i < rows; ++i) {
    z[i] = new PLFLT[col];
    for (int j = 0; j < col; ++j) {
        z[i][j] = data[i][j]; // 行i、列j,与data结构一致
    }
}

4. std::min/std::max用法错误

std::min(z, z + (rows * col))是错误用法:z是二维指针数组,std::min会比较指针地址而非元素值,且z + rows*col超出z的实际范围,解引用后访问非法内存。

修复:
遍历二维数组计算z的最小/最大值:

PLFLT zmin = z[0][0];
PLFLT zmax = z[0][0];
for (int i = 0; i < rows; ++i) {
    for (int j = 0; j < col; ++j) {
        if (z[i][j] < zmin) zmin = z[i][j];
        if (z[i][j] > zmax) zmax = z[i][j];
    }
}

5. PLplot imagefr参数不匹配

imagefr函数中nx是x方向点数(列数),ny是y方向点数(行数),原代码传入的rows和col顺序颠倒,导致绘图时内存访问异常。

修复:

pls->imagefr(z, col, rows, xmin, xmax, ymin, ymax, zmin, zmax, 0, 0, 0, 0);

6. 内存泄漏问题

创建的plstream和z数组未释放,虽不直接引发segfault,但会导致内存泄漏,需补充释放逻辑:

修复:
在函数末尾添加:

// 释放z数组
for (int i = 0; i < rows; ++i) {
    delete[] z[i];
}
delete[] z;
// 释放plstream对象
delete pls;

修正后的完整代码示例

头文件引用

#include <iostream>
#include <string.h>
#include <plplot/plstream.h>
#include <plplot/plplot.h>
#include <fstream>
#include <vector>
#include <sstream>

using namespace std;

#define NSIZE    101

读取数据函数

// 读取文本文件数据
std::vector<std::vector<int> > readData(const std::string& filename) {
    std::vector<std::vector<int> > data;
    std::ifstream file(filename.c_str());
    std::string line;

    if (!file.is_open()) {
        std::cerr << "Unable to open file " << filename << std::endl;
        exit(1);
    }

    while (std::getline(file, line)) {
        std::istringstream iss(line);
        std::vector<int> row;
        int value;
        while (iss >> value) {
            row.push_back(value);
        }
        if(!row.empty())
        {
            data.push_back(row);
        }
    }
    file.close();
    return data;
}

绘制颜色图函数

void createColourMap(const std::vector<std::vector<int> >& data)
{
    if (data.empty()) {
        std::cerr << "Error: No data to plot." << std::endl;
        return;
    }
    int rows = data.size();
    int col = data[0].size();
    
    plstream *pls = new plstream();
    pls->sdev("xwin");
    pls->init();

    pls->env(0.0, rows, 0.0, col, 1, -1);
    pls->lab("X", "Y", "Colour Map Example");

    // 按行分配二维数组,匹配data结构
    PLFLT **z = new PLFLT*[rows];
    for (int i = 0; i < rows; ++i) {
        z[i] = new PLFLT[col];
        for (int j = 0; j < col; ++j) {
            z[i][j] = data[i][j];
        }
    }

    pls->scmap1l(true, 256, NULL, NULL, NULL, NULL);

    PLFLT xmin = 0.0, xmax = static_cast<PLFLT>(rows - 1);
    PLFLT ymin = 0.0, ymax = static_cast<PLFLT>(col - 1);
    
    // 计算z的最小最大值
    PLFLT zmin = z[0][0];
    PLFLT zmax = z[0][0];
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < col; ++j) {
            if (z[i][j] < zmin) zmin = z[i][j];
            if (z[i][j] > zmax) zmax = z[i][j];
        }
    }

    pls->col0(1);
    // 修正imagefr参数顺序:nx为列数,ny为行数
    pls->imagefr(z, col, rows, xmin, xmax, ymin, ymax, zmin, zmax, 0, 0, 0, 0);

    // 释放内存
    for (int i = 0; i < rows; ++i) {
        delete[] z[i];
    }
    delete[] z;
    delete pls;
}

主函数

int main( int argc, char *argv[] )
{
    std::vector<std::vector<int> > data;
    data = readData("Test.txt");

    createColourMap(data);

    return 0;
}

额外排查建议

  • 确认Test.txt格式:每行数值数量一致,避免data中各行列数不同引发索引越界。
  • 使用调试工具定位问题:编译时添加-g参数,通过gdb运行程序,触发错误后用bt命令查看调用栈,明确错误代码行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:40:55