1. 程式人生 > >開啟檔案失敗返回EMFILE的問題分析

開啟檔案失敗返回EMFILE的問題分析

## 查詢官網錯誤程式碼 在官網中查詢到返回值為24對應的錯誤資訊為EMFILE,對應的描述資訊為**EMFILE    Too many open files    24**,對應的中文翻譯就是開啟的檔案太多.具體參考網址為:[https://msdn.microsoft.com/en-us/library/t3ayayh1.aspx](https://msdn.microsoft.com/en-us/library/t3ayayh1.aspx),對應的中文參考網址為:[https://msdn.microsoft.com/zh-cn/magazine/t3ayayh1.aspx](https://msdn.microsoft.com/zh-cn/magazine/t3ayayh1.aspx).由於是第一次碰到這種問題,且每次呼叫後我在解構函式中都呼叫了close,難道是fclose沒有將FILE*關閉.windows系統存在這麼明顯的bug?顯然是不可能的. 使用其它開啟檔案命令無法檢視到返回錯誤資訊的情況下可以通過上面的_wfopen_s來看看具體的錯誤值. ##除錯fclose## 通過debug單步跟蹤發現如下的呼叫關係: 1. fclose 2. _fclose_nolock 3. _close(_fileno(stream)) 其中可以看到_fileno中獲取的是stream中的_file,也就是檔案no.具體FILE*的結構體如下: ``` struct _iobuf {         char *_ptr;         int   _cnt;         char *_base;         int   _flag;         int   _file;//檔案控制代碼         int   _charbuf;         int   _bufsiz;         char *_tmpfname;         }; ``` 通過除錯這裡發現此處檔案很明顯是關閉了的.

## 偉大的_fcloseall()

通過查詢發現有個NB的函式可以關掉所有的控制代碼,直接在釋放位置呼叫該方法_fcloseall(),再進行測試,此時長時間執行都未出現問題.可惜由於應用的需要不能使用該方法,故可以肯定是在某個位置出現了控制代碼的記憶體洩漏.

## 輸出發現大玄機

通過在fclose前面輸出FILE* fp的fp->_file資訊,通過測試發現該值不斷增大當增大到512左右的時候,程式就出現了檔案再也無法開啟的情況.按道理windows系統中除了標準輸入、標準輸出和錯誤輸出後_file不應該出現無限增加的情況,初步推斷windows一個程序最多可以支援開啟512個檔案(未驗證,據說linux的是1024,按道理這應該是可以配置的系統引數).

## 後續

通過追蹤肯定是控制代碼問題後,通過逐步排查最終找到了檔案未關閉的位置.