C++ std::filesystem::exists()返回false,尽管文件确实存在 const std::string propName(pPropName,len); std::filesystem::path p(pPropName); 如果(!std::filesystem::exists(p)){ 日志(日志::级别::错误, “文件%s不存在,长度=%u”, propName.c_str(), len); 返回; }

C++ std::filesystem::exists()返回false,尽管文件确实存在 const std::string propName(pPropName,len); std::filesystem::path p(pPropName); 如果(!std::filesystem::exists(p)){ 日志(日志::级别::错误, “文件%s不存在,长度=%u”, propName.c_str(), len); 返回; },c++,g++,c++17,C++,G++,C++17,出于某种原因,在卷中有几次std::filesystem::exists(p)返回false(在我修改了现有文件并用vi保存后),而该文件确实存在--我立即对该文件执行ls-ed操作 boost::filesystem::exists()中报告了类似的问题 其中一个答案建议vi在保存文件之前创建一个临时文件(即:w)。但是,上面的代码是在我点击:wq!几秒钟后手动触发的在vi中。我甚至在1分2秒后又试了两次std::filesystem::exists()仍然返回false 另一个答案表明这可能

出于某种原因,在卷中有几次
std::filesystem::exists(p)
返回
false
(在我修改了现有文件并用
vi
保存后),而该文件确实存在--我立即对该文件执行
ls
-ed操作

boost::filesystem::exists()
中报告了类似的问题

其中一个答案建议
vi
在保存文件之前创建一个临时文件(即
:w
)。但是,上面的代码是在我点击
:wq!几秒钟后手动触发的
vi
中。我甚至在1分2秒后又试了两次
std::filesystem::exists()
仍然返回
false

另一个答案表明这可能是一个许可问题。但是,我的情况并非如此,因为在11分钟后,相同的代码和相同的二进制文件看到了该文件(即
std::filesystem::exists()
返回
true
),我甚至没有重新启动进程(其中包含上述代码)

困难之处在于它不是100%可复制的——我只是编辑了上面的代码,以传入
std::error\u code
的一个实例,尝试获取错误代码。但我现在无法复制它

有什么想法吗

我使用
g++
8.3.1进行编译,代码在CentOS 7.7上运行

=====

更新#1:文件大小约为5190字节,位于3+GHz Intel服务器上的SSD上

更新#2:这是
策略的输出(在
std::filesystem::exists(p)
返回true时捕获):


更新#3:发现问题--
pPropName
有时可能不以null结尾(应该使用
propName
)。并且
std::error\u code.message().c\u str()
返回“Success”,奇怪。无论如何,谢谢大家。

实际上是
vi
在创建新文件之前重命名了目标文件(这让我很惊讶)

我在编辑一个文件(
the_文件
)时运行这个程序来验证它

验证这一点的一种简单方法是在使用
vi
之前和之后检查文件的
inode
编号。打开一个文件并执行
:wq
将创建一个新文件,其中包含一个新的
inode
编号

但这并不能解释为什么文件在很长一段时间后不可见。那可能是因为某个地方有一些藏品。显然,XFS文件系统存在(或曾经存在)一些问题,其缓存没有针对小文件进行正确更新。如果
存在(p)=false
,也许您可以添加此选项:

system("sync;sync;sync"); // old classic tripple sync

将缓存写入同步到永久性存储。在那之后,再检查一遍。

我并不是说这就是正在发生的事情(这是非常不寻常的):如果文件在写下来之前被
vi
(作为最后的手段)取消链接,这可能会发生。假设您有删除目录中文件的完全权限,但没有更新实际文件的权限。删除该文件并写入新文件将起作用。否则,
vi
很可能会写入一个临时文件并将其移动到适当的位置,这样
存在(p)
将始终成功。@TEDLYNGOM感谢您分享您的想法。奇怪的是,即使在2分钟后,我仍然点击了
:wq
vi
中,尽管
ls
看到了该文件,但上面的代码仍然无法看到该文件。移动文件需要2分钟,特别是SSD上的文件只有5190字节。您能
strace
查看底层(失败的)系统调用的过程吗?@Botje我在工作时间以外尝试复制时尝试这么做(在工作时间内,我不允许造成任何不稳定…
strace
通常会以毫秒级降低速度,这在我的业务案例中是不可接受的)。我认为在gcc-8下,如果编译时没有明确链接到stdc++fs(即:
--std=c++17-lstdc++fs
),我会有一些奇怪的行为…我完全忘记了原因和方式,感谢您通过详细分析检查了
vi
的行为。如果xfs缓存了,因此没有立即将缓冲区刷新回磁盘,我想知道
ls
是如何看到文件的,以及
vi
是如何看到缓存内容的(就像我再次看到
vi
以及我在那里看到的修改一样).是的,关于XFS的部分很难实现,但仍然值得尝试
sync
,看看它是否有任何效果。
#include <filesystem>
#include <iostream>
int main() {
    std::filesystem::path p("the_file");
    while(std::filesystem::exists(p));
    std::cout << "gone\n";
}
read(0, "\r", 250)                      = 1
select(1, [0], [], [0], {tv_sec=0, tv_usec=0}) = 0 (Timeout)
write(1, "\r", 1)                       = 1
stat("/home/ted/proj/stackoverflow/the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
access("/home/ted/proj/stackoverflow/the_file", W_OK) = 0
write(1, "\33[?25l\33[?2004l\33[>4;m", 20) = 20
ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(1, "\"the_file\"", 10)            = 10
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
access("the_file", W_OK)                = 0
getxattr("the_file", "system.posix_acl_access", 0x7fffb80a2f50, 132) = -1 ENODATA (No data available)
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
lstat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
lstat("4913", 0x7fffb80a32e0)           = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "4913", O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0100644) = 3
fchown(3, 1000, 100)                    = 0
stat("4913", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
close(3)                                = 0
unlink("4913")                          = 0
stat("the_file~", 0x7fffb80a3000)       = -1 ENOENT (No such file or directory)
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
stat("the_file~", 0x7fffb80a1fd0)       = -1 ENOENT (No such file or directory)
unlink("the_file~")                     = -1 ENOENT (No such file or directory)
rename("the_file", "the_file~")         = 0
openat(AT_FDCWD, "the_file", O_WRONLY|O_CREAT, 0644) = 3
ftruncate(3, 0)                         = 0
write(3, "hejsan\n", 7)                 = 7
fsync(3)                                = 0
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
fchmod(3, 0100644)                      = 0
close(3)                                = 0
setxattr("the_file", "system.posix_acl_access", "\2\0\0\0\1\0\6\0\377\377\377\377\4\0\4\0\377\377\377\377 \0\4\0\377\377\377\377", 28, 0) = 0
write(1, " 1L, 7C written", 15)         = 15
stat("/home/ted/proj/stackoverflow/the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
unlink("the_file~")                     = 0
write(1, "\r\r\n\33[?2004l\33[?1l\33>", 18) = 18
write(1, "\33[?25h\33[>4;m\33[?1049l\33[23;0;0t", 29) = 29
close(4)                                = 0
unlink("/home/ted/proj/stackoverflow/.the_file.swp") = 0
exit_group(0)                           = ?
+++ exited with 0 +++
system("sync;sync;sync"); // old classic tripple sync