创建新文件时避免竞态条件

9
我需要开发一个C++例程来执行这个看似微不足道的任务:仅在文件不存在时创建文件,否则不执行任何操作/引发错误。
由于我需要避免竞态条件,我想使用“先行请求原谅不要事先获得许可”的原则(即尝试预期的操作并检查它是否成功,而不是事先检查前提条件),据我所知,这是唯一可靠且可移植的方法[维基百科文章][使用getline的示例]
然而,我找不到实现它的方法。我能想到的最好的方法是以app模式打开fstream(或者用"a"打开fopen),使用tellp(C ++)或ftell(C)检查输出位置,并在该位置不为零时中止。但是,这有两个缺点,即如果文件存在,则会被锁定(虽然只有短时间)并且其修改日期会更改。
我检查了fstream的其他可能的ios_base::openmode组合,以及fopenmode字符串,但没有找到适合我的需求的选项。进一步在C和C ++标准库以及Boost Filesystem中搜索均无结果。
有人能指出一种在不依赖于特定于操作系统的功能的情况下以稳健方式执行我的任务的方法吗?我的具体问题在Windows中,但是最好使用可移植解决方案。
编辑:BitWhistler的答案完全解决了C程序的问题。仍然令我惊讶的是,似乎不存在符合C++惯用法的解决方案。或者使用Andrew Henle提出的带有O_EXCL属性的open(但在Windows中,该属性似乎称为带有额外下划线的_O_EXCL[MSDN]),或者单独编译一个C11文件并从C ++代码链接它。此外,获取的文件描述符无法转换为流,除非使用非标准扩展(例如GCC的__gnu_cxx :: stdio_filebuf )。我希望C ++的未来版本将实现"x"子属性,可能还会为文件流实现相应的ios :: 修改器。

你想要避免多个线程或多个进程之间的竞态条件吗? - user2807083
3
你使用的操作系统是什么?POSIX提供了open( filename, O_CREAT | O_EXCL ... )可以完成你想要做的事情。 - Andrew Henle
1
Win32 API可以做到这一点。我非常确定。 - Kirill Kobelev
2
我从不做你似乎在提出的事情。如果有多个线程需要写入一个文件,我会将输出排队到一个线程中,该线程管理文件并执行所有输出。文件系统上的竞争消失了,调试变得更加容易,管理输出文件(例如限制其大小,每天选择一个新文件)变得微不足道。 - Martin James
抱歉没有说明清楚:这里可能存在竞争条件,是由于我无法控制的外部进程引起的。我完全同意应该由单个线程执行应用程序中的I/O操作。 - Alberto M
显示剩余3条评论
1个回答

3
新的C标准(C2011,不是C++的一部分)添加了一个新的标准子说明符(“x”),可以附加到任何“w”说明符(形成“wx”,“wbx”,“w+x”或“w+bx” / “wb + x”)。此子说明符会强制函数在文件存在时失败,而不是覆盖它。
来源:http://www.cplusplus.com/reference/cstdio/fopen/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接