使用fread读取指针指向的多元素时出现段错误,原因是什么?
fread批量读取触发段错误的原因分析
首先看定义的结构体:
typedef struct { int nr_operations; int *operations_idxs; } sensor;
尝试从文件读取operations_idxs指向的数组元素时,以下代码会出现段错误:
S[i].operations_idxs=(int*)malloc(S[i].nr_operations*sizeof(int)); fread(&S[i].operations_idxs, sizeof(int), S[i].operations_idxs, f);
而通过循环逐个读取的代码可以正常获取数据:
S[i].operations_idxs=(int*)malloc(S[i].nr_operations*sizeof(int)); for( j=0; j<S[i].nr_operations; j++) { fread(&S[i].operations_idxs[j], sizeof(int), 1, f); }
错误根源在于fread的参数完全用错了:
- 第一个参数错误:
&S[i].operations_idxs是取指针变量自身的地址,而我们需要写入的是指针指向的malloc分配好的内存区域,应该直接传递S[i].operations_idxs(指针变量的值就是目标内存的起始地址)。如果传指针的地址,fread会把文件内容覆盖掉指针本身存储的malloc返回的有效地址,后续再通过这个指针访问内存时,就会指向非法地址,触发段错误。 - 第三个参数错误:fread的第三个参数是要读取的元素个数,你传入的
S[i].operations_idxs是一个指针,会被强制转换成整数(也就是malloc返回的内存地址,通常是一个很大的数值),fread会尝试读取这么多个int元素,远远超出了分配的内存大小和文件中的实际数据量,直接导致内存越界访问,触发段错误。正确的元素个数应该是S[i].nr_operations。
正确的批量fread写法:
S[i].operations_idxs = (int*)malloc(S[i].nr_operations * sizeof(int)); // 目标内存地址 | 单个元素大小 | 元素个数 | 文件指针 fread(S[i].operations_idxs, sizeof(int), S[i].nr_operations, f);
内容的提问来源于stack exchange,提问作者Chipuc Valentin
相关产品推荐
相关产品推荐

