fopen操作导致文件名错乱、被修改的原因及解决方法
问题原因与解决方案
问题原因
- 内存分配严重不足:你用
malloc(sizeof(char))只分配了1字节的内存,但要存储的是原文件名file_name加上后缀.ob的完整字符串,长度远大于1字节。执行strcpy和strcat时会直接发生缓冲区溢出,破坏堆内存的结构,甚至覆盖相邻内存区域的数据。 - 堆内存被破坏后的连锁反应:缓冲区溢出已经打乱了堆内存的正常布局,后续调用
fopen时,标准库内部的堆内存操作会进一步修改被破坏的内存区域,导致两次打印的full_file_name内容出现错乱。
解决方案
方法一:手动计算所需内存并分配
先计算完整文件名的总长度(原文件名长度 + 后缀长度 + 字符串结束符\0的1字节),再分配对应大小的内存,同时要检查内存分配是否成功:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 假设file_name是已定义的有效字符串 char* file_name = "test"; int main() { // 计算完整文件名所需的总内存 size_t total_length = strlen(file_name) + strlen(".ob") + 1; char *full_file_name = malloc(total_length); FILE *ob_file; // 检查内存分配是否成功 if (full_file_name == NULL) { perror("malloc failed"); return 1; } // 拼接文件名 strcpy(full_file_name, file_name); strcat(full_file_name, ".ob"); printf("\n full_file_name :%s", full_file_name); // 创建文件 ob_file = fopen(full_file_name, "w"); printf("\n full_file_name :%s", full_file_name); // 用完内存后释放 free(full_file_name); // 记得关闭文件 if (ob_file != NULL) { fclose(ob_file); } return 0; }
方法二:用snprintf安全拼接(更推荐)
snprintf可以先计算所需的字符串长度,再分配内存,避免手动计算长度出错:
#include <stdio.h> #include <stdlib.h> #include <string.h> char* file_name = "test"; int main() { char *full_file_name = NULL; // 先计算拼接后字符串的长度(不含结束符) size_t total_length = snprintf(NULL, 0, "%s.ob", file_name) + 1; full_file_name = malloc(total_length); FILE *ob_file; if (full_file_name == NULL) { perror("malloc failed"); return 1; } // 安全拼接字符串 snprintf(full_file_name, total_length, "%s.ob", file_name); printf("\n full_file_name :%s", full_file_name); ob_file = fopen(full_file_name, "w"); printf("\n full_file_name :%s", full_file_name); free(full_file_name); if (ob_file != NULL) { fclose(ob_file); } return 0; }
内容的提问来源于stack exchange,提问作者Eitan Ratner
相关产品推荐
相关产品推荐

