1. 程式人生 > >fopen返回空指標

fopen返回空指標

背景:測試部說錄影不成功,經小維查明是fopen返回NULL導致

工程程式碼:
FILE* pFile = fopen(recPath, "wb");
if (NULL == pFile)
{
     printf("fopen return NULL, error=%d/n", GetLastError());
}
失敗時列印:fopen return NULL, error=0
繼續執行時列印:fopen return NULL, error=183

分析(懷疑是fopen後未fclose所致,寫一測試程式碼):
int i = 0;
for (i = 0; i < 1000; i++)
{
      pFile = fopen(sPath, "wb");//sPath每次都不同
      if (NULL == pFile)
      {
             printf("[%d]fopen return NULL, error=%d/n", i, GetLastError());
       }
}
在winxp下測試,發現前508個檔案都沒問題,509個檔案開始都是返回NULL,並且error=0
關閉程式再執行一次,一樣,前508個檔案都沒問題,但是error=183
error=183的意思是:當檔案已存在時,無法建立該檔案。

改為CreateFile再測,1000個檔案建立成功,沒有出錯

結論:
1、GetLastError()並不能精確實時獲取fopen的錯誤,
2、fopen控制代碼數目有限制
建議:
1、fopen後一定要fclose
2、建議win下用CreateFile代替fopen

聽說linux下fopen控制代碼數目只能支援17個?有興趣的朋友可測試一下

linux下面的fd限制

如果不考慮記憶體大小的限制,在linux下面,fd (即file descriptor)的數量來自2個限制(閾值)。

其一:是作業系統的限制。
這個限制主要是在linux核心中,我們知道,使用者程式的fopen操作最後都通過system call進入到linux kenrel。
linux kernel會對此進行檢查,防止某個使用者佔用太多的系統資源。
現在的核心都可以通過sysctl命令在開機的時候來調整。他是不是還有一個程式碼級別的最大值(如定義了巨集),我沒有仔細研究關於此的程式碼,故不能確定。但據我所知,某些程式開上萬個fd也是有在用的。

命令sysctl fs.file-max=655360可以調整核心的閾值,當然你得有root許可權。想一勞永逸,參考/etc/sysctl.conf,用命令man sysctl.conf
命令sysctl -a可以顯示所有的能夠調整引數。

其二:是使用者程序的限制。
舉例,在bash環境下啟動的程式將繼承bash預設的或使用者定製的限制。
這個限制可以通過bash的內部命令ulimit來調整,當然不能高過作業系統的限制。
比如命令:ulimit -n 20規定了在當前bash環境下執行的程式只能同時開啟20個fd,但是如果你做上面的測試程式,則只有17個。還有3個哪裡去了?動腦筋想一下你應該能找到答案。
ulimit -n 命令只能往下調fd,不能往上調。如果你改的過小了,想反悔?好像只能關閉當前的bash再重新開啟一個。
那麼,bash又是從哪裡繼承的呢?參考/etc/security/limits.conf,用命令man limits.conf

ulimit -a可以顯示包括fd在內的全部閾值:如最大資料段大小、最大程式碼段大小、最大棧大小、使用者能建立的程序的最大數目、一個程序中執行緒的最大數目。
試試在s2伺服器上執行此命令,結果應該是最大可同時開啟1024個fd。
尋求更多的資訊?老辦法:輸入命令man bash,然後查詢ulimit。