使用nftw时如何避免使用全局变量

use*_*847 9 c global-variables nftw

我想使用nftw遍历C中的目录结构.

但是,考虑到我想要做的事情,我没有看到使用全局变量的方法.

使用(n)ftw的教科书示例都涉及执行类似打印文件名的操作.相反,我希望获取路径名和文件校验和并将它们放在数据结构中.但考虑到可以传递给nftw的限制,我没有看到一个很好的方法.

我正在使用的解决方案涉及一个全局变量.然后,nftw调用的函数可以访问该变量并添加所需的数据.

没有使用全局变量有没有合理的方法呢?

这是关于stackoverflow的上一篇文章中的交换,有人建议我将其作为后续发布.

Kje*_*röm 5

使用ftw可能真的非常糟糕。在内部,它将保存您使用的函数指针,如果另一个线程执行了其他操作,它将覆盖该函数指针。

恐怖场景:

thread 1:  count billions of files
thread 2:  delete some files
thread 1:  ---oops, it is now deleting billions of 
              files instead of counting them.
Run Code Online (Sandbox Code Playgroud)

简而言之。您最好使用fts_open。

如果您仍要使用nftw,那么我的建议是将“全局”类型放在名称空间中,并将其标记为“ thread_local”。您应该能够根据需要进行调整。

/* in some cpp file */
namespace {
   thread_local size_t gTotalBytes{0};  // thread local makes this thread safe
int GetSize(const char* path, const struct stat* statPtr, int currentFlag, struct FTW* internalFtwUsage) {
    gTotalBytes+=  statPtr->st_size;
    return 0;  //ntfw continues
 }
} // namespace


size_t RecursiveFolderDiskUsed(const std::string& startPath) {
   const int flags = FTW_DEPTH | FTW_MOUNT | FTW_PHYS;
   const int maxFileDescriptorsToUse = 1024; // or whatever
   const int result = nftw(startPath.c_str(), GetSize, maxFileDescriptorsToUse , flags);

  // log or something if result== -1
  return gTotalBytes;
}
Run Code Online (Sandbox Code Playgroud)

  • glibc的ftw实现将函数指针保存在堆栈中,而不是全局变量中,因此您列出的恐怖场景是不可能的。就是说,我认为您对使用thread_local的建议是此问题的最佳答案。 (2认同)

jpa*_*cek 3

nftw提供任何可以传递给函数的用户参数,因此您必须在 C 中使用全局(或静态)变量。

GCC 提供了一个扩展“嵌套函数”,它应该捕获其封闭范围的变量,因此可以像这样使用它们:

void f()
{
  int i = 0;
  int fn(const char *,
    const struct stat *, int, struct FTW *) {
    i++;
    return 0;
  };
  nftw("path", fn, 10, 0);
}
Run Code Online (Sandbox Code Playgroud)