调用fread后Valgrind报Conditional jump or move depends on uninitialised value错误
错误原因排查
- 字符串终止符下标设置错误
你通过fread读取了length个字节存入buffer,有效数据的下标范围是0 ~ length-1,C语言字符串要求以'\0'结尾,你应该将终止符写入buffer[length]的位置,而你的代码写在了buffer[length+1]的位置:- 导致
buffer[length]属于完全未初始化的堆内存 printf用%s输出字符串时会调用strlen计算长度,遍历到未初始化的buffer[length]时就触发了Valgrind的Conditional jump or move depends on uninitialised value(s)报错
- 导致
- 缺少空指针安全校验
如果malloc分配内存失败返回NULL,你直接执行buffer[length+1]='\0'会直接触发段错误。 - 未校验
fread的返回值
如果文件读取过程中出现异常,fread实际读取的字节数会小于传入的length参数,此时buffer中未被写入的区域同样属于未初始化内存,输出时也会触发同类报错。 - 类型匹配问题
ftell的返回值类型是long,你用int类型存储存在溢出风险,当读取的文件大小超过int的取值范围时会导致内存分配大小错误,进而引发更多内存问题。
修复后的参考代码
char* readFile(char* filename){ FILE * f = fopen(filename, "rb"); if (!f) { printf("failed to open file\n"); return NULL; } printf("sucessfully opened file\n"); fseek(f, 0, SEEK_END); long length = ftell(f); fseek(f, 0, SEEK_SET); // 按需分配内存,多1字节用于存储字符串终止符即可 char* buffer = malloc(length + 1); if (!buffer) { printf("malloc buffer failed\n"); fclose(f); return NULL; } size_t read_cnt = fread(buffer, 1, length, f); // 按实际读取的字节数设置终止符 buffer[read_cnt] = '\0'; fclose(f); printf("buffer: %s",buffer); return buffer; }
内容的提问来源于stack exchange,提问作者Magie99b
相关产品推荐
相关产品推荐

