2010-04-07 66 views
4

我碰到下面的代碼在我們內部的DLL一個跑了,我想了解它顯示的行爲:爲什麼在fopen()不關閉後調用close()?

long GetFD(long* fd, const char* fileName, const char* mode) 
{ 
    string fileMode; 

    if (strlen(mode) == 0 || tolower(mode[0]) == 'w' || tolower(mode[0]) == 'o') 
     fileMode = string("w"); 
    else if (tolower(mode[0]) == 'a') 
     fileMode = string("a"); 
    else if (tolower(mode[0]) == 'r') 
     fileMode = string("r"); 
    else 
     return -1; 

    FILE* ofp; 
    ofp = fopen(fileName, fileMode.c_str()); 
    if (! ofp) 
     return -1; 

    *fd = (long)_fileno(ofp); 
    if (*fd < 0) 
     return -1; 

    return 0; 
} 

long CloseFD(long fd) 
{ 
    close((int)fd); 
    return 0; 
} 

與適當CloseFD,整個DLL會GetFD反覆呼叫後沒有更能夠做任何文件IO。我寫了一個測試程序,發現我可以GetFD 509次,但第510次會出錯。

使用Process Explorer,Handles的數量沒有增加。

因此,似乎dll達到打開文件的數量的限制;設置_setmaxstdio(2048)確實增加了我們可以調用GetFD的次數。顯然,close()工作非常正確。

有點搜索後,我更換了fopen()呼叫搭配:

long GetFD(long* fd, const char* fileName, const char* mode) 
{ 
    *fd = (long)open(fileName, 2); 
    if (*fd < 0) 
     return -1; 

    return 0; 
} 

現在,一邊喊GetFD/CloseFD工作。

這是怎麼回事?

回答

17

如果用fopen打開文件,則必須對稱地用fclose關閉它。

C++運行時必須有機會清理/取消分配其內部文件相關結構。

+10

具體來說,你會留下一堆FILE *結構,一些操作系統有一個固定大小的表,通常是512,其中包括stdin,stdout和stderr FILE * s。 – 2010-04-07 12:47:14

+4

...這解釋了509的限制:它只是512 - 標準輸入 - 標準輸出 - 標準錯誤。 – Vlad 2010-04-07 12:49:58

+2

'stdio'運行時,不僅僅是C++(即,對於C和C++都是通用的)。 – mpez0 2010-04-07 12:55:44

8

您需要使用fclose以及通過fopenclose打開的文件以及通過open打開的文件。

5

您正在使用的標準庫有一個FILE結構的靜態數組。由於您沒有調用fclose(),因此標準庫不知道底層文件已關閉,因此它不知道它可以重用相應的FILE結構。在FILE陣列中的條目用完之後您會收到錯誤消息。

3

fopen打開它自己的文件描述符,因此您需要在原始函數中執行fclose(ofp)以防止耗盡文件描述符。通常,要麼使用較低級別的文件描述符函數open, close,要麼使用緩存的fopen, fclose函數。

2

你打開文件fopen()函數功能,使u必須關閉文件期運用FCLOSE(),如果你使用的是open()函數,並嘗試FCLOSE()函數調用它不會工作

相關問題