C语言文件导入场景下的内存问题排查:munmap_chunk()无效指针错误及strtof使用疑问
问题分析与修复方案
首先,Valgrind报的Use of uninitialised value of size 8错误确实和strtof()的使用直接相关,但根源不是函数本身用错了,而是你给它的输入不是合法的C风格字符串。
核心问题:字符串s缺少终止空字符
C语言里,像strtof()这类字符串处理函数要求输入必须是以'\0'结尾的合法字符串。但你的代码里,只是把每行的字符逐个塞进s数组,却没有在最后添加终止符:
for (int i=0; c != '\n'; ++i) { s[i] = c; c = fgetc(fptr); } // 这里没有加 s[i] = '\0';
这会导致strtof()读取s数组时,超出你填充的字符范围,访问到数组里未初始化的内存,正好对应Valgrind的报错。
其他潜在内存问题
除了终止符的问题,你的代码还有几个可能引发内存破坏的点,这也可能是munmap_chunk(): invalid pointer错误的根源(即使你注释了free(),之前的内存破坏已经损坏了堆结构,后续操作会触发错误):
s数组可能越界写入
你的循环没有限制i的最大值,如果某行的字符数超过12(s的大小是13,索引0-12),就会写出数组边界,破坏堆内存。'S'的处理逻辑有漏洞
当遇到'S'时,你直接跳过两个字符,但如果'S'后面紧跟的是换行符,第二个fgetc()会读取到换行,后续的字符处理逻辑会混乱,可能把无效字符塞进s数组。未处理文件末尾(EOF)的情况
如果fgetc()返回EOF(文件读完了),你的代码没有判断,会继续执行循环,导致读取无效的字符值。
修复后的代码示例
void import_bn(int depth, int idx, float pdata[4][depth]) { // [0][:] is gamma, [1][:] is beta, [2][:] is moving mean, [3][:] is moving variance // Define name from index char name[12]; // maximum number of characters is "paramxx.csv" = 11 sprintf(name, "param%d.csv", idx); // open file FILE *fptr; fptr = fopen(name, "r"); if (fptr == NULL) { perror("fopen()"); exit(EXIT_FAILURE); } int c; // 用int存fgetc的返回值,才能正确判断EOF char s[13] = {0}; // 初始化数组,避免未初始化内存 char* a; // pointer for strtof for (int t = 0; t < 4; ++t) { // type for (int d = 0; d < depth; ++d) { // depth // 跳过所有空白字符和分隔符'S' while ((c = fgetc(fptr)) != EOF) { if (c != ' ' && c != '\t' && c != '\n' && c != 'S') { break; } } if (c == EOF) { fprintf(stderr, "Unexpected end of file\n"); fclose(fptr); exit(EXIT_FAILURE); } // 写入字符串,同时限制长度避免越界 int i = 0; for (; c != '\n' && c != EOF && i < 12; ++i) { s[i] = c; c = fgetc(fptr); } s[i] = '\0'; // 添加终止空字符! float f = strtof(s,&a); // 现在输入是合法的C字符串了 pdata[t][d] = f; // save on array } } fclose(fptr); }
修复要点说明
- 把
char c改成int c:因为fgetc()返回EOF时是一个int类型的值(通常是-1),用char存会丢失这个判断。 - 初始化
s数组为全0:避免未初始化的内存被读取。 - 添加终止空字符
s[i] = '\0':确保strtof()能正确识别字符串结束位置。 - 限制
s的写入长度:i < 12保证不会写出数组边界。 - 优化分隔符和空白字符的处理:用循环跳过所有无效字符(包括'S'、换行、空格),确保每次读取的都是有效数字字符。
- 增加EOF判断:避免文件读完后继续执行错误逻辑。
这些修复应该能解决Valgrind的未初始化值错误,同时修复潜在的内存破坏问题,进而解决munmap_chunk()的错误。
内容的提问来源于stack exchange,提问作者Ricardo
相关产品推荐
相关产品推荐

