如何避免使用nftw在使用全局变量(How avoid using global variable

2019-06-23 21:28发布

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

然而,鉴于我想做的事情,我没有看到周围使用全局变量的方式。

使用(n)的课本上的例子FTW都涉及做这样打印出的文件名。 我想,而是采取了路径名和文件校验,并将那些数据结构。 但我没有看到一个很好的方式做到这一点,因为什么可以传递给nftw的限制。

我使用该解决方案包括一个全局变量。 然后通过nftw调用的函数可以访问该变量并添加所需的数据。

是否有任何合理的方式做到这一点不使用全局变量?

这里有一个计算器在以前的帖子交流中,有人建议我张贴这是一个后续。

Answer 1:

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);
}


Answer 2:

使用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. 

简而言之。 你最好使用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;
}


Answer 3:

该数据最好给出静态链接(即文件范围)在一个单独的模块,其包括仅访问数据所需要的功能,包括传递给函数nftw() 这样的数据是不是全局可见,所有的访问控制。 这可能是调用ntfw()函数也是这个模块的一部分,从而使传递到nftw()的函数也是静态的,并且因此不可见的外部。

换句话说,你应该做你可能做的事情了,但使用不同的编译和静态链接明智使数据只能通过访问功能可见。 与静态链接的数据是由同一个翻译单元中的任何功能的访问,您应避免那些创造者,维护者或数据的存取仅包括在翻译单元的功能与全局变量相关的问题。

一般的模式是:

datamodule.h

#if defined DATAMODULE_INCLUDE
<type> create_data( <args>) ;
<type> get_data( <args> ) ;
#endif

datamodule.c

#include "datamodule.h"

static <type> my_data ;

static int nftwfunc(const char *filename, const struct stat *statptr, int fileflags, struct FTW *pfwt)
{
    // update/add to my_data
    ...
}


<type> create_data( const char* path, <other args>)
{
    ...

    ret = nftw( path, nftwfunc, fd_limit, flags);

    ... 
}

<type> get_data( <args> )
{
    // Get requested data from my_data and return it to caller
}


文章来源: How avoid using global variable when using nftw