含转义字符的文件名无法通过sprintf拼接路径的修复问题
修复含反斜杠文件名的路径拼接问题
我写了一个C语言函数,用来接收目录路径和文件名,通过检查目录末尾是否带/来拼接完整路径。但发现如果文件名里包含\字符,sprintf就没法正确拼接字符串;文件名不含\时一切正常,该怎么修复?
我的代码如下:
char * find_endwith_slash(char *dir_path, char *file_name) { char full_path[1024]; if (dir_path[strlen(dir_path) - 1] != '/') { sprintf(full_path, "%s/%s", dir_path, file_name); } else { sprintf(full_path, "%s%s", dir_path, file_name); } char * full_name = malloc(strlen(full_path) * sizeof(char)); full_name = strdup(full_path); return full_name; }
问题根源
sprintf的转义特性:sprintf会把输入字符串里的\当成转义符处理(比如\n会被解析为换行),而非普通字符,导致文件名中的反斜杠被错误解析,最终拼接结果不符合预期。- 栈缓冲区溢出风险:
full_path是固定大小的栈数组(1024字节),如果拼接后的路径长度超过这个值,会触发缓冲区溢出,引发未定义行为。 - 内存泄漏:先
malloc分配内存,随后用strdup的返回值覆盖指针,导致malloc的内存永远无法释放。
修复方案
方案1:用strcpy+strcat替代sprintf(推荐)
字符串拼接函数会直接复制所有普通字符,不会处理转义,完美适配带反斜杠的文件名:
char * find_endwith_slash(char *dir_path, char *file_name) { size_t dir_len = strlen(dir_path); size_t file_len = strlen(file_name); // 计算总内存:目录长度 + 可能的1个/ + 文件名长度 + 1(字符串终止符) size_t total_len = dir_len + (dir_path[dir_len - 1] != '/' ? 1 : 0) + file_len + 1; char *full_name = malloc(total_len); if (!full_name) return NULL; // 必须检查内存分配是否成功 strcpy(full_name, dir_path); if (dir_path[dir_len - 1] != '/') { strcat(full_name, "/"); } strcat(full_name, file_name); return full_name; }
方案2:改用snprintf替代sprintf(如果坚持用格式化函数)
snprintf可以避免缓冲区溢出,同时只要文件名里的\是原始字符(不是转义后的),直接使用即可:
char * find_endwith_slash(char *dir_path, char *file_name) { size_t dir_len = strlen(dir_path); size_t file_len = strlen(file_name); size_t total_len = dir_len + (dir_path[dir_len - 1] != '/' ? 1 : 0) + file_len + 1; char *full_name = malloc(total_len); if (!full_name) return NULL; if (dir_path[dir_len - 1] != '/') { snprintf(full_name, total_len, "%s/%s", dir_path, file_name); } else { snprintf(full_name, total_len, "%s%s", dir_path, file_name); } return full_name; }
关键修复点
- 移除了内存泄漏:直接根据实际需求分配内存,不再重复分配后丢弃指针。
- 消除栈溢出风险:用动态分配的堆内存替代固定大小的栈数组。
- 增加内存分配失败检查:避免返回空指针导致后续操作崩溃。
内容的提问来源于stack exchange,提问作者devMe
相关产品推荐
相关产品推荐

