我在我们的一个内部dll中遇到了以下代码,我试图理解它显示的行为:
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重复调用GetFD后,整个dll将无法再执行任何文件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可以正常工作。
这里发生了什么?
答案 0 :(得分:17)
如果您使用fopen
打开文件,则必须以fclose
对称关闭它。
必须为C ++运行时提供清理/解除分配其内部文件相关结构的机会。
答案 1 :(得分:8)
您需要将fclose
与通过fopen
打开的文件一起使用,或close
打开通过open
打开的文件。
答案 2 :(得分:5)
您使用的标准库具有FILE
结构的静态数组。因为您没有调用fclose()
,所以标准库不知道底层文件已被关闭,因此它不知道它可以重用相应的FILE
结构。在FILE
数组中的条目用完后,您会收到错误。
答案 3 :(得分:3)
fopen
打开它自己的文件描述符,因此您需要在原始函数中执行fclose(ofp)
以防止文件描述符用完。通常,要么使用较低级别的文件描述符函数open, close
,要么使用缓冲的fopen, fclose
函数。
答案 4 :(得分:2)
你打开文件fopen()函数所以你必须关闭文件使用fclose(),如果你使用open()函数并尝试调用fclose()函数它将无法正常工作