数组操作遇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
相关产品推荐
相关产品推荐

