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

数组操作遇Segmentation fault及数据读取异常求助

ExtractNumber函数的内存访问与数据读取异常排查与修复

问题场景

定义了ExtractNumber函数,用于从动态分配的字符串数组(每行格式为double,double)中提取数值,存储到两个动态分配的double数组中。原调用方式:

ExtractNumber(Array, &Numbers1, &Numbers2);

其中char** Array是从标准输入读取的字符串数组,double* Numbers1、double* Numbers2是存储提取结果的动态数组。

原代码与初始问题

原ExtractNumber实现

//char** array是从标准输入读取字符串直到EOF的动态分配数组
//double** Numbers1和double** Numbers2是在main中分配的用于存储double值的数组

void ExtractNumber (char **array, double **Numbers1, double **Numbers2)
{
    double a,b;
    char* str;
    //ArrMax为存储数组行数的变量
    for (int i = 0; i < *ArrMax; i++)
    {
        str = array[i];
        printf ("\n%s\n", str);
        sscanf(str, "%lf,%lf",&a, &b);
        *Numbers1[i] = a;
        *Numbers2[i] = b;
        printf ("%lf %lf",(*Numbers1)[i] , (*Numbers2)[i]);
    }
}

原main函数实现

//LenMax用于计算Array的行数
int main ()
{
    char** Array;
    int LenMax;
    double * Numbers1;
    double * Numbers2;

    printf ("Insert string:\n");
    Array = ReadArray(&LenMax);
    
    Numbers1 = (double*) malloc (sizeof (Numbers1) * LenMax);
    Numbers2 = (double*) malloc (sizeof (Numbers2) * LenMax);

    ExtractNumber(Array, &Numbers1, &Numbers2);

    for (int i = 0; i < LenMax; i++)
        printf ("%lf\n", Numbers1[i]);

    for (int i = 0; i<LenMax;i++)
    {
        free (Array[i]);
    }
    
    return 0;
}

初始问题

函数内部printf输出正常,但运行时触发Segmentation fault (core dumped),外部printf输出(null)。

修改后的代码与新问题

修改后的ExtractNumber函数新增了行数参数ArrMax,段错误消失,但输入2行数据时,仅第一行数值被正确读取,第二行数值为0:

void ExtractNumber (char ** array, double ** Num1, double ** Num2, int ArrMax)
{
    double a,b;
    char* str;
    //ArrMax为存储数组行数的变量
    for (int i = 0; i < ArrMax; i++)
    {
        str = array[i];
        sscanf(str, "%lf,%lf",&a, &b);
        *Num1[i] = a;
        *Num2[i] = b;
    }
}

问题根源与修复方案

1. 指针优先级错误(核心问题)

C语言中数组下标运算符[]优先级高于解引用*,*Num1[i]等价于*(Num1[i])——而Num1是double**类型,Num1[i]会访问指针数组的第i个元素,但我们实际要操作的是main中分配的double数组(即*Num1,double*类型),正确写法应为(*Num1)[i]。

原代码和修改后的代码都存在这个错误:

  • 原代码中越界访问触发段错误
  • 修改后的代码仅i=0时Num1[0]恰好等于*Num1,所以第一行数据正常,后续i>=1时访问非法内存,数值被初始化为0。

2. 内存分配错误

main中malloc的参数错误:sizeof(Numbers1)是指针大小(通常8字节),而非double类型大小,正确写法应为sizeof(double),确保分配足够内存存储LenMax个double值:

Numbers1 = (double*) malloc (sizeof(double) * LenMax);
Numbers2 = (double*) malloc (sizeof(double) * LenMax);

3. 参数传递问题

原ExtractNumber函数中*ArrMax未作为参数传入,属于未定义行为;修改后新增ArrMax参数是正确的,需在main调用时传入LenMax:

ExtractNumber(Array, &Numbers1, &Numbers2, LenMax);

修复后的完整代码

修复后的ExtractNumber

void ExtractNumber (char ** array, double ** Num1, double ** Num2, int ArrMax)
{
    double a,b;
    char* str;
    for (int i = 0; i < ArrMax; i++)
    {
        str = array[i];
        // 检查sscanf返回值,确保读取成功
        if (sscanf(str, "%lf,%lf", &a, &b) == 2) {
            (*Num1)[i] = a;
            (*Num2)[i] = b;
        } else {
            // 处理读取失败的情况
            (*Num1)[i] = 0.0;
            (*Num2)[i] = 0.0;
            fprintf(stderr, "Failed to parse line %d: %s\n", i, str);
        }
    }
}

修复后的main函数

int main ()
{
    char** Array;
    int LenMax;
    double * Numbers1;
    double * Numbers2;

    printf ("Insert string:\n");
    Array = ReadArray(&LenMax);
    
    // 修正内存分配的sizeof参数
    Numbers1 = (double*) malloc (sizeof(double) * LenMax);
    Numbers2 = (double*) malloc (sizeof(double) * LenMax);

    // 传入LenMax作为行数参数
    ExtractNumber(Array, &Numbers1, &Numbers2, LenMax);

    for (int i = 0; i < LenMax; i++)
        printf ("%lf\n", Numbers1[i]);

    // 释放所有动态分配的内存
    for (int i = 0; i<LenMax;i++)
    {
        free (Array[i]);
    }
    free(Array);
    free(Numbers1);
    free(Numbers2);
    
    return 0;
}

额外建议

  • 始终检查malloc返回值,避免内存分配失败导致后续错误
  • 检查sscanf返回值,确保每行数据被正确解析
  • 释放所有动态分配的内存,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:55:18