C++ 写入文件,st#mtime不';不变

C++ 写入文件,st#mtime不';不变,c++,c,linux,posix,C++,C,Linux,Posix,我有一个程序,想检查一个文件是否被修改。regtest失败,事实上,尽管文件已更改,st_mtime没有!此外,外部统计数据也证实了这一点 我相信Stu_mtime应该改变,因为统计数据(2)显示 字段st_mtime通过文件修改进行更改,例如,通过mknod(2)、truncate(2)、utime(2)和write(2)(大于零字节)进行更改 下面是一段C代码,说明了这一点: #include <assert.h> #include <stdio.h> #includ

我有一个程序,想检查一个文件是否被修改。regtest失败,事实上,尽管文件已更改,
st_mtime
没有!此外,外部统计数据也证实了这一点

我相信Stu_mtime应该改变,因为统计数据(2)显示

字段st_mtime通过文件修改进行更改,例如,通过mknod(2)、truncate(2)、utime(2)和write(2)(大于零字节)进行更改

下面是一段C代码,说明了这一点:

#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


void touch(const char *fn, const char *contents)
{
    FILE *fp;
    assert(fp = fopen(fn, "w"));
    fprintf(fp, contents);
    fclose(fp);
}


int main( int argc, char *argv[] )
{
    struct stat st;
    char path[] = "/tmp/foo";
    time_t m1, m2;
    unsigned int t;

    touch(path, "hello\n");
    assert(!stat(path, &st));
    m1 = st.st_mtime;

    touch(path, "hello, world!\n");
    t = sleep(2);
    assert(!stat(path, &st));
    m2 = st.st_mtime;

    printf("Sleep remaining: %lu\n", t);
    printf("Elapsed modtime=%lu\n", m2 - m1);
}

切勿在有副作用的函数上使用
断言

始终这样做:

FILE * fp;
fp = fopen(...);

assert(fp != NULL);

包含
assert()
的整行将从发布版本中消失。

切勿在具有副作用的函数上使用
assert

始终这样做:

FILE * fp;
fp = fopen(...);

assert(fp != NULL);

包含
assert()
的整行内容将从发布版本中消失。

首先,我强烈建议您不要在
assert
s中使用带有副作用的语句。我知道这很方便,如果代码永远不会投入生产,那也不重要,但它不是好的形式。特别是,如果您定义了
NDEBUG
,那么
断言将转换为noop,条件的代码将永远不会执行

现在,问题很可能是您将
sleep
调用放在两个
touch
调用之后,而不是放在它们之间。更改此项:

touch(path, "hello\n");
assert(!stat(path, &st));
m1 = st.st_mtime;

touch(path, "hello, world!\n");
t = sleep(2);
assert(!stat(path, &st));
m2 = st.st_mtime;


首先,我强烈建议您不要在
assert
s中使用带有副作用的语句。我知道这很方便,如果代码永远不会投入生产,那也不重要,但它不是好的形式。特别是,如果您定义了
NDEBUG
,那么
断言将转换为noop,条件的代码将永远不会执行

现在,问题很可能是您将
sleep
调用放在两个
touch
调用之后,而不是放在它们之间。更改此项:

touch(path, "hello\n");
assert(!stat(path, &st));
m1 = st.st_mtime;

touch(path, "hello, world!\n");
t = sleep(2);
assert(!stat(path, &st));
m2 = st.st_mtime;


如何更改您检查的文件?在分析代码之前,可能值得考虑该步骤中的错误。函数touch()进行更改。它只是“echo$1>/tmp/foo”的C等价物。查看shell中的文件,我确认它包含第二次更改的内容,但包含第一次更改的modtime!某些装载选项可能会影响索引节点内mtime的更新方式。@Basile-true,但在这种情况下,代码是错误的。但是,这些装载选项会在文件关闭时更新元数据。McKusick的BSD ffs早在20世纪80年代就意识到了这个问题,也就是说,每次物理写入更新元数据(如mtime)都会带来额外的开销,因为这意味着磁盘上会有一个额外的i/o。如何更改检查的文件?在分析代码之前,可能值得考虑该步骤中的错误。函数touch()进行更改。它只是“echo$1>/tmp/foo”的C等价物。查看shell中的文件,我确认它包含第二次更改的内容,但包含第一次更改的modtime!某些装载选项可能会影响索引节点内mtime的更新方式。@Basile-true,但在这种情况下,代码是错误的。但是,这些装载选项会在文件关闭时更新元数据。McKusick的BSD ffs早在20世纪80年代就意识到了这个问题,也就是说,每次物理写入更新元数据(如mtime)都会带来额外的开销,因为这意味着磁盘会有一个额外的i/o。嗯,是的,我是个白痴。谢谢你给我指出显而易见的。。。这是一个来自一些相当复杂的代码的人为例子,我清楚地校对了我认为我写的东西。而现实生活中更复杂的代码也有同样的错误。我比我梦想的更坚定。嗯,是的,我是个白痴。谢谢你给我指出显而易见的。。。这是一个来自一些相当复杂的代码的人为例子,我清楚地校对了我认为我写的东西。而现实生活中更复杂的代码也有同样的错误。我比我梦想的更坚定。同意,谢谢。在这个扔掉的例子中,它的意思是排除例子中错误的返回值。同意,谢谢。在这个扔掉的示例中,它意味着排除示例中错误的返回值。