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 手册所说的几点看明白的话,出现上面的原因也就很好解释了:

  1. mktemp 返回的是被修改后的模板字符串指针
  2. 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 使用需谨慎,认真对待编译器警告/
作者
非典型技术宅
发布于
2022年9月4日
许可协议