【问题标题】:Error while accessing multiple files repeatedly重复访问多个文件时出错
【发布时间】:2019-05-21 09:50:42
【问题描述】:

我有一个 C++ 和一个 Python 代码通过在一个目录中读取和写入文件来相互通信,多次。他们还在读取数据后删除了一些文件。这是在 Ubuntu 17.10 上完成的。

但是,在多次执行此序列(>6000 - 7000 次)之后,我收到以下错误:

Couldn't open the directory: Too many open files

此错误消息始终从 C++ 代码传递。

对于C++代码

数据写入使用:

std::string opfilepath("/some/path/");
ofstream opfile;
opfile.open (opfilepath);
opfile<<"some stuff"<<endl;
opfile.close()

目录中的文件数使用以下方法计算:

DIR* dirFile = opendir( path );
int count = 0;
if ( dirFile ) 
{
  struct dirent* hFile;
  errno = 0;
  while (( hFile = readdir( dirFile )) != NULL ) 
  {
     if ( !strcmp( hFile->d_name, "."  )) continue;
     if ( !strcmp( hFile->d_name, ".." )) continue;

     if ( strstr( hFile->d_name, ext.c_str() ))
        count++;
  } 

}
closedir( dirFile );

读取文件使用:

std::ifstream file("/some/path");
if (file.is_open())
    {
      //do something
    }
file.close();

文件被删除使用:

boost::filesystem::remove("/some/file.txt")

对于 Python 代码:

文件使用以下方式写入:

f = open("/some/file.txt", "a")
f.write("some stuff")
f.close()

使用以下方式读取文件:

fp = open(path)
lines = fp.read().splitlines()
fp.close()

文件被删除使用:

os.remove("/some/path/and/file.txt")

所有文件都以模块化方式打开和关闭,同步似乎不是问题。但我一直看到打开的文件太多,而且总是在固定数量的迭代之后。

任何想法为什么会发生这种情况?

【问题讨论】:

  • 这是否在多个线程或进程中运行?围绕此代码是否有任何错误处理,或者是否有可能捕获到不关闭文件的异常?通常最好使用适当的错误处理(在 python 中使用with 语句)进行文件操作,并在 C 中使用 try catch 块来确保即使在文件打开和文件关闭之间引发异常的情况下也能关闭文件。
  • 你可以检查你的“ulimit -n”参数,还提供进程抛出错误打开的文件描述符的总数,你可以这样做 - ls /proc//fd |厕所-l。这将使您了解文件描述符发生了什么。
  • 哪个进程收到Couldn't open the directory: Too many open files 错误消息? C++ 那个? Python 那个?
  • @metsburg 继续检查命令“lsof -p ”的输出,它将为您提供导致问题的未打开文件的确切名称。正如你所说,这是一个新的观察结果,没有。 fd 随时间增加,如果不是。每次迭代的 fd 都在增加 - 始终如一,那么可以看出您应该在迭代中的相关点使用带有断点的 gdb 以及 lsof 使用 - 来根本导致确切的问题。
  • @metsburg 或者您可以运行 valgrind --track-fds=yes /path/to/cppBin,请注意,这些只是缩小范围的技术。

标签: python c++ file-io resource-leak


【解决方案1】:

无法打开目录:打开的文件太多

这意味着您的进程已超过分配给它的最大打开文件参数,请参阅使用 ulimit -a 或 ulimit -n。您的进程可能合法地需要更多 fd - 如果是这种情况,请增加 ulimit -n 并在同一个 shell 中启动该进程,否则请按照下面提到的。

如果您想查看打开文件描述符的趋势,请使用ls /proc/&lt;pid&gt;/fd | wc -l 查看它,它将让您深入了解进程如何处理打开的文件。

这个问题似乎是文件描述符泄漏,所以要轻松解决它,请使用lsof -p &lt;pid&gt; 查看所有打开的文件,这可以提供有用的提示。

如果没有任何效果,并且问题看起来很复杂,那么使用 valgrind 分析并使用 track-fd=yes 标志 valgrind --track-fds=yes /path/to/cppBin 来查看导致 fd 泄漏的确切堆栈。

【讨论】:

    猜你喜欢
    • 2018-12-21
    • 2020-10-27
    • 2012-04-10
    • 1970-01-01
    • 2020-08-03
    • 2010-10-16
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多