2012-01-05 91 views
1

我有一個程序要檢查文件是否已被修改。註冊失敗,事實上,儘管文件已更改,st_mtime還沒有!此外,外部統計也證實了這一點。寫入文件,st_mtime不會更改

我相信st_mtime 應該變化,因爲統計(2)說

領域st_mtime是通過文件的修改改變,例如,通過用mknod(2),截斷(2),UTIME(2)和寫(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); 
} 

這裏的東西提供給打壞,以確認它不只是在C程序中的緩存:

$,而真正;做stat/tmp/foo | grep修改;睡眠1;完成

有什麼建議發生了什麼? FWIW,這是可鑑定的系統上運行:

[email protected]:src $ uname -a 
Linux london 2.6.32-37-generiC#81-Ubuntu SMP Fri Dec 2 20:32:42 UTC 2011 x86_64 GNU/Linux 
[email protected]:src $ 
+0

你如何改變你檢查文件?在分析代碼之前,可能需要考慮該步驟中的錯誤。 – Sim 2012-01-05 20:54:31

+0

touch()函數進行更改。它只是「echo $ 1>/tmp/foo」的C等價物。 – jma 2012-01-05 20:55:22

+0

從shell中查看文件,我確認它具有來自第二次更改的內容,但是從第一次更改了modtime! – jma 2012-01-05 21:00:04

回答

3

首先,我強烈建議您不要在assert之內使用帶副作用的語句。我明白這很方便,如果代碼永遠不會生產,它並不重要,但它不是很好的形式。特別是,如果您定義了NDEBUG,則assert會轉換爲noop,但條件的代碼永遠不會執行。

現在,問題很可能是您在撥打touch後調用sleep調用,而不是調用它們。更改此:

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(path, "hello\n"); 
int rv = stat(path, &st); 
assert(!rv); 
m1 = st.st_mtime; 

t = sleep(2); 

touch(path, "hello, world!\n"); 
int rv = stat(path, &st); 
assert(!rv); 
m2 = st.st_mtime; 
+0

恩,是的,我是個白癡。感謝您指出我顯而易見的......這是一些相當複雜的代碼的一個人爲的例子,我清楚地校對了我認爲我寫的東西。 – jma 2012-01-05 21:04:59

+1

而現實生活中的代碼複雜得多,也有同樣的錯誤。我比我敢於夢想的更一致。 – jma 2012-01-05 21:07:47

1

切勿使用上的功能assert有副作用!

始終做到這一點:

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

assert(fp != NULL); 

包含assert()自發布消失構建整條生產線。

+0

同意,謝謝。在這個拋棄的例子中,它的意思是在這個例子中排除不良的返回值。 – jma 2012-01-05 21:06:12