C语言程序生成文件名时偶现异常字符的问题求助
C程序生成文件名时出现随机异常字符的修复方案
问题背景
程序需实现两个功能:
- 接收命令行参数,移除标点并转小写后拼接成字符串
- 为字符串添加日期前缀生成最终文件名
执行命令:
./cprog -md I am cre,ating a .md file
预期生成文件名:
2023_12_15_i_am_cre_ating_a__md_file.md
但约25%概率出现异常输出:
'2023_12_15_'$''\002'i_am_cre_ating_a__md_file.md'
问题代码片段
标点移除与参数拼接代码
for ( int arg = 0; arg < argc; arg++ ){ for ( int let = 0; let < strlen(argv[arg]); let++ ){ if ( !ispunct( argv[arg][let] ) ){ argv[arg][let] = tolower( argv[arg][let] ); } else { argv[arg][let] = 95; } } strcat( filename, argv[arg] ); }
日期生成与文件名拼接代码
time_t rawtime = time(NULL); struct tm *ptm = localtime(&rawtime); char filename_date[12]; char result[ strlen(filename_date) + strlen(filename) ]; strftime( filename_date, sizeof(filename_date), "%Y_%b_%d", ptm ); sprintf( result, "%s_%s.md", filename_date, filename ); strcpy( filename, result ); create_md( filename );
核心问题分析
未初始化数组的长度计算:
char result[ strlen(filename_date) + strlen(filename) ];中,filename_date是未初始化的局部数组,内存为随机垃圾值,strlen会读取到随机的终止位置,导致result数组大小不足,后续sprintf写入时越界,破坏内存产生异常字符。直接修改
argv内存的风险:argv指向的命令行参数内存在部分系统中是只读的,直接修改会触发未定义行为;同时若filename未初始化为空字符串,strcat操作也会读取随机内存。日期格式符不匹配预期:
代码中用%b(月份缩写,如Dec),但预期是数字月份,需改为%m。
修复代码示例
修复后的参数处理代码
// 确保filename预先初始化为空,比如: char filename[1024] = {0}; for (int arg = 0; arg < argc; arg++) { char temp[256] = {0}; // 临时缓冲区处理单个参数 size_t arg_len = strlen(argv[arg]); for (int let = 0; let < arg_len; let++) { // 用unsigned char避免tolower/ispunct处理负数值的未定义行为 unsigned char c = argv[arg][let]; if (!ispunct(c)) { temp[let] = tolower(c); } else { temp[let] = '_'; } } strcat(filename, temp); }
修复后的日期与文件名拼接代码
time_t rawtime = time(NULL); struct tm *ptm = localtime(&rawtime); char filename_date[12]; // 先填充日期字符串,确保内容有效 strftime(filename_date, sizeof(filename_date), "%Y_%m_%d", ptm); // 计算所需缓冲区大小,包含日期、下划线、原文件名、.md和终止符 size_t result_size = strlen(filename_date) + strlen(filename) + 4; char *result = malloc(result_size); if (result == NULL) { perror("malloc failed"); return 1; } sprintf(result, "%s_%s.md", filename_date, filename); strcpy(filename, result); free(result); // 释放动态分配的内存 create_md(filename);
关键修复点总结
- 初始化所有字符串缓冲区,避免读取随机内存
- 不直接修改
argv,改用临时缓冲区处理参数 - 先填充日期数组再计算最终文件名的缓冲区大小,或使用足够大的固定缓冲区
- 修正日期格式符为
%Y_%m_%d以匹配预期的数字月份格式
内容的提问来源于stack exchange,提问作者Nully
相关产品推荐
相关产品推荐

