c++如何利用tmpfile函数自动创建并管理匿名临时文件【详解】

雨涛大大_7938

雨涛大大_7938

2026-03-26

465人浏览

原创

tmpfile() 创建的文件退出即消失,因其返回前已 unlink(),仅靠 file* 句柄维持内核引用;进程终止或 fclose() 后自动释放。

c++如何利用tmpfile函数自动创建并管理匿名临时文件【详解】

tmpfile() 创建的文件为什么一退出就消失?

tmpfile() 在 C 标准库中直接调用系统接口(如 Linux 的 open("/dev/null", ...) 或更常见的是 mkstemp() 配合 unlink())创建一个无路径名的文件,句柄返回后立即被 unlink() —— 这意味着它没有目录项指向,但只要进程还持有 FILE*,内核仍保留其数据。进程终止、或显式 fclose() 后,系统自动回收空间。

常见错误现象:fopen("temp.dat", "w") 生成的文件会残留磁盘;而 tmpfile() 却怎么也找不到对应文件名,甚至 lsof -p $PID 都只看到 (deleted) —— 这不是 bug,是设计使然。

  • 它不写入任何目录,ls /tmp 永远看不到它
  • 不能用 fseek() 随机读写?可以,但得确保文件流是可定位的(tmpfile() 返回的是二进制读写流,默认支持 fseek)
  • Windows 下行为一致,但底层用的是类似 GetTempFileName() + DeleteFile() 组合

tmpfile() 和 tmpfile_s() 在 C++ 里怎么选?

C++ 程序若混用 C 风格 I/O,优先用 tmpfile();若项目启用了安全增强(如 MSVC 的 SDL 检查),编译器可能报错:"tmpfile() has been deprecated" —— 此时需改用 C11 的 tmpfile_s(),但它不是 C++ 标准函数,且 MSVC 实现要求传入缓冲区大小参数,glibc 则未实现。

使用场景:tmpfile_s() 并非“更安全”,只是把错误码从全局 errno 改为输出参数,避免多线程竞争;但 C++ 项目中更自然的做法是绕过 C FILE*,改用 RAII 方式管理临时文件。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • tmpfile():POSIX/C99 兼容,所有主流平台可用,返回 FILE*
  • tmpfile_s(size_t *restrict psize):仅 Windows/MSVC 有完整实现,Linux 上需手动定义或跳过
  • 现代 C++ 更推荐 std::filesystem::temp_directory_path() + std::filesystem::create_temporary_file()(C++17 起),它返回真实路径,便于调试

tmpfile() 返回 NULL 怎么排查?

典型错误信息:tmpfile() returned NULL,常见原因不是磁盘满,而是进程级资源限制或权限问题。

  • 检查 ulimit -n:如果进程打开文件数已达上限,tmpfile() 会失败(即使你刚 fclose 了几个)
  • 确认 /tmp 所在文件系统是否只读(mount | grep "$(df . | tail -1 | awk '{print $1}')”)
  • 某些容器环境(如 rootless Podman)默认禁用 memfd_create 或 tmpfs 写入,也会静默失败
  • 务必检查返回值:if (!fp) { perror("tmpfile"); return -1; },不要假设它一定成功

用 tmpfile() 做缓存时要注意什么?

有人用 tmpfile() 当做大对象缓冲区(比如下载中间体、图像处理暂存),这可行,但容易忽略两个关键点:内存映射开销和生命周期绑定。

性能影响:Linux 下 tmpfile() 多数走 tmpfs(即内存文件系统),读写快,但会占用 RAM 或 swap;如果写入 500MB,实际就是占了 500MB 可用内存 —— 不是“不占资源”的幻觉。

  • 别在循环里反复 tmpfile() + fclose():每次都会触发一次 unlink + 新分配,开销比复用一个流高
  • 如果需要多次读写同一块临时数据,rewind(fp) 比重新 fopen 更轻量
  • 跨线程传递 FILE* 是危险的:C 标准不保证 FILE* 线程安全,除非用 flockfile(),但会拖慢速度;更适合用 std::vector<uint8_t></uint8_t> 或 mmap 替代

最常被忽略的一点:tmpfile() 创建的是文本模式流(即使你没指定 b),在 Windows 上换行符会被自动转换;若写二进制数据,必须用 fwrite() 并确认 ferror(),否则可能静默截断。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end='\n', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.27

2940

5

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

2026.02.03

249

24

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1698

6

fclose函数的用法
fclose函数的用法

fclose是一个C语言和C++中的标准库函数,用于关闭一个已经打开的文件,是文件操作中非常重要的一个函数,用于将文件流与底层文件系统分离,释放相关的资源。更多关于fclose函数的相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.30

822

9

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3148

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

4949

12

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.12.29

3789

9

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

2026.01.19

446

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习