mktemp 使用需谨慎,认真对待编译器警告
mktemp 使用需谨慎,认真对待编译器警告
絮絮叨叨:今天在做一个文件缓存管理的时候,使用 mktemp 生成一个临时文件名,在编译时编译器提示我,该函数不安全,头铁的我还是使用了。
然后我就变成这样了
代码复现
mktemp 的作用是根据传入的字符串模板,生成一个临时文件名。
char path[PATH_MAX] = "test_XXXXXX";
temp_tath = mktemp(path);
printf("path:%s\n", temp_tath);
// 输出 test_ZjSxUe
这段代码时简单的复现了一下当时的场景,看看你能发现其中的 bug 不~
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void){
char path[PATH_MAX] = "test_XXXXXX";
char *temp_tath;
for (size_t i = 0; i < 3; i++){
temp_tath = mktemp(path);
printf("path:%s\n", temp_tath);
}
}
// 预期结果:
path:test_hMLBpq
path:test_Ig8q7p
path:test_Xs1OTp
// 实际结果:
path:test_tEb4Mt
path:
path:
如果你是第一次使用这个函数,又没有好好看文档的话,很可能会掉进坑里面去。。
mktemp 正确用法
这是 man 手册中关于 mktemp 使用的介绍。
大概意思为:
mktemp 使用时传入最后六个字符为 XXXXXX
的模板字符串 ,它就会将最后六个字符替换,以生成唯一的文件名。
mktemp 的返回值为总是为传入的模板字符串,在输入格式错误时,将会把模板字符串清空(空字符串)。
如果把 man 手册所说的几点看明白的话,出现上面的原因也就很好解释了:
mktemp
返回的是被修改后的模板字符串指针- 当
mktemp
输入的模板字符串格式不正确时,将清空模板字符串,而不是返回一个空指针(我就是这么理解的🤦♂️)
所以正确的使用方法是:
int main(void){
char path[PATH_MAX] ;
char *temp_tath;
for (size_t i = 0; i < 3; i++)
{
strcpy(path, "test_XXXXXX");
temp_tath = mktemp(path);
printf("path:%s\n", temp_tath);
}
}
不安全原因
在我定位到问题原因后以为这么就是编译器提示不安全的原因,但是在看完文档后才知道这只是我用法出错了。
在 man 手册中对于不安全原因的描述为:
大概意思是:mktemp
实现时使用进程ID和单个字母组成,所以最多只有26种不同的名字。这种名字很容易被猜到,而且在测试文件名是否存在时,可能会与已经打开的文件产生竞争。
所以以后在使用新的函数或者接口时,要多看看官方文档啊!
这应该不是第一次,也不太可能是最后一次,只是提醒自己慢即是快。
mktemp 使用需谨慎,认真对待编译器警告
https://gary-hobson.github.io/2022/09/04/mktemp 使用需谨慎,认真对待编译器警告/