首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >尽管文件确实存在,std::filesystem::exists()仍返回false

尽管文件确实存在,std::filesystem::exists()仍返回false
EN

Stack Overflow用户
提问于 2020-07-17 22:41:20
回答 1查看 2.3K关注 0票数 2
代码语言:javascript
运行
复制
const std::string propName(pPropName, len);
std::filesystem::path p(pPropName);
if (!std::filesystem::exists(p)) {
    LOG(    Log::Level::ERROR,
            "File %s does not exist w/len = %u",
            propName.c_str(),
            len);
    return;
}

由于某些原因,当文件确实存在时,std::filesystem::exists(p)返回false (在我修改现有文件并用vi保存之后)的情况在滚动中发生过几次--我立即对该文件执行ls-ed。

boost::filesystem::exists()中也有a very similar post报告类似的问题。

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

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

最困难的部分是它不是100%可重现的--我只是编辑了上面的代码,传入了std::error_code的一个实例,试图获得错误代码。但我现在不能重现它。

有什么想法吗?

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

=

更新#1:文件大小约为5190字节,位于3+GHz英特尔服务器的固态硬盘上。

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

代码语言:javascript
运行
复制
stat("/server/my_file.ini", {st_mode=S_IFREG|0775, st_size=5077, ...}) = 0
open("/server/my_file.ini", O_RDONLY) = 15

更新#3:发现了这个问题-- pPropName有时可能不会以null结尾(应该使用propName)。std::error_code.message().c_str()返回"Success",很奇怪。不管怎样,谢谢大家。

EN

回答 1

Stack Overflow用户

发布于 2020-07-18 22:13:20

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

我通过在编辑文件(the_file)时运行此程序进行了验证。

代码语言:javascript
运行
复制
#include <filesystem>
#include <iostream>
int main() {
    std::filesystem::path p("the_file");
    while(std::filesystem::exists(p));
    std::cout << "gone\n";
}

vi中执行:wq时,程序会打印gone并退出。

此外,vi会话的strace会对此进行验证。这是按回车键返回命令:wq后的strace -ff日志。注意renameopenat序列:

代码语言:javascript
运行
复制
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)
代码语言:javascript
运行
复制
rename("the_file", "the_file~")         = 0
openat(AT_FDCWD, "the_file", O_WRONLY|O_CREAT, 0644) = 3
代码语言:javascript
运行
复制
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 +++

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

但是,这并不能解释为什么文件在很长一段时间后不可见。这可能是因为某些地方的缓存。显然,XFS文件系统有(或有)一些问题,即它的缓存没有为小文件正确更新。也许你可以添加这个,如果exists(p) == false

代码语言:javascript
运行
复制
system("sync;sync;sync"); // old classic tripple sync

将缓存的写操作同步到持久性存储。在此之后,请尝试再次检查它。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62956322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档