是否正在两个不同的fstream中打开SAME文件未定义的行为?

问题描述 投票:5回答:4

[recently asked question提出了另一个有趣的问题,如comments to one of its answers中所述。

总结:OP在随后尝试从两个流“同时”读取/写入两个流中的数据时,以下代码存在问题:ifstream infile; infile.open("accounts.txt"); ofstream outfile; outfile.open("accounts.txt");

尽管该问题本身已被成功解决,但它提出了一个我无法找到权威答案的问题(并且我对Stack Overflow和更广泛的网络进行了相当广泛的搜索。

非常清楚地说明,调用已经与

file

open())相关联的streamcppreference方法时会发生什么,但是我找不到答案是什么当(在这种情况下)file已与(不同)stream关联时发生。
[如果流已经与文件关联(即,它已经打开),则调用此函数失败。

我可以在这里看到几种可能的情况:

    第二个打开的调用将失败,并且对其进行任何尝试的写入也将失败(但是在引用的问题中是
  1. not。)>第二个打开的调用将“覆盖”第一个打开的调用,有效地将其关闭(此
  2. 可以解释所述代码中遇到的问题)。
  3. 两个流都保持打开状态,但在内部文件指针和缓冲区方面陷入了相互破坏”。
  4. 我们进入未定义(或实现定义)行为的领域。
  5. 请注意,由于第一个open()调用是由输入流进行的,因此操作系统不一定会“锁定”文件,就像可能会针对输出流进行锁定。

  6. 所以,有人对此有明确的答案吗?还是来自标准的引用(如果找不到更多权威,则引用是“可接受的”)?

[这个最近问到的问题提出了另一个有趣的问题,如对其答案之一的评论中所讨论。总结一下:当...

basic_filebuf::open(以及依赖它的所有事物,例如fstream::open)都没有声明这种情况下会发生什么。文件系统可能允许也可能不允许。

标准说的是,如果文件成功打开,则可以根据界面进行播放。如果未成功打开,则将出现错误。也就是说,该标准允许文件系统允许或禁止它,但没有说明必须发生的情况。该实现甚至可以随机禁止它。或禁止您以任何方式打开任何文件。从理论上讲,所有这些都是有效的。

对我来说,这甚至不属于“实现定义”字段。完全相同的代码将具有不同的行为,具体取决于基础文件系统或操作系统(某些操作系统禁止两次打开文件)。

编号

标准不讨论这种情况。

甚至不由实现(您的编译器,标准库的实现等)管理。

该流最终要求操作系统以所需的方式访问该文件,并且由操作系统决定是否应在那个时候准许该访问。

一个简单的类比是您的程序通过网络对Web应用程序进行一些API调用。也许该Web应用程序每分钟不允许超过10个呼叫,并且如果尝试超过此次数,则会返回一些错误代码。但这并不意味着您的程序在这种情况下会有未定义的行为。

C实现存在于许多不同的平台,它们的基础文件系统可能以不同的方式处理这种极端情况。为了使标准强制要求任何特殊的极端情况,该语言只能在其文件系统以这种方式运行的平台上实用。相反,该标准认为此类问题不在其管辖范围之内(即使用其自己的术语“未定义的行为”)。这并不意味着目标OS提供有用保证的实现不应在可行时对程序做出这样的保证,而是假定实现设计者比委员会更了解如何最好地为他们的客户服务。

另一方面,对于实现

not

公开底层OS行为有时可能会有所帮助。例如,在没有独特的“追加”模式的操作系统上,但是需要“打开以追加”的代码可以执行“打开现有文件以进行写入”,然后执行“寻找文件结尾”的尝试,打开两个流以将其追加到同一文件时,当一个流写入文件的一部分,而另一个流随后重写同一部分时,则可能导致数据损坏。对于检测该条件的实现而言,注入自己的逻辑以确保数据的平滑合并或阻止第二个打开请求可能会有所帮助。根据应用程序的目的,这两种方法中的任何一种都可能更好,但是-如上所述-选择不在标准的管辖范围内。
c++ fstream undefined-behavior
4个回答
2
投票
basic_filebuf::open(以及依赖它的所有事物,例如fstream::open)都没有声明这种情况下会发生什么。文件系统可能允许也可能不允许。

标准说的是,如果文件成功打开,则可以根据界面进行播放。如果未成功打开,则将出现错误。也就是说,该标准允许文件系统允许或禁止它,但没有说明必须发生的情况。该实现甚至可以随机禁止它。或禁止您以任何方式打开任何文件。从理论上讲,所有这些都是有效的。


1
投票
对我来说,这甚至不属于“实现定义”字段。完全相同的代码将具有不同的行为,具体取决于基础文件系统或操作系统(某些操作系统禁止两次打开文件)。

1
投票
编号

1
投票
C实现存在于许多不同的平台,它们的基础文件系统可能以不同的方式处理这种极端情况。为了使标准强制要求任何特殊的极端情况,该语言只能在其文件系统以这种方式运行的平台上实用。相反,该标准认为此类问题不在其管辖范围之内(即使用其自己的术语“未定义的行为”)。这并不意味着目标OS提供有用保证的实现不应在可行时对程序做出这样的保证,而是假定实现设计者比委员会更了解如何最好地为他们的客户服务。

另一方面,对于实现

not

公开底层OS行为有时可能会有所帮助。例如,在没有独特的“追加”模式的操作系统上,但是需要“打开以追加”的代码可以执行“打开现有文件以进行写入”,然后执行“寻找文件结尾”的尝试,打开两个流以将其追加到同一文件时,当一个流写入文件的一部分,而另一个流随后重写同一部分时,则可能导致数据损坏。对于检测该条件的实现而言,注入自己的逻辑以确保数据的平滑合并或阻止第二个打开请求可能会有所帮助。根据应用程序的目的,这两种方法中的任何一种都可能更好,但是-如上所述-选择不在标准的管辖范围内。
© www.soinside.com 2019 - 2024. All rights reserved.