首页 > 解决方案 > 为什么 opendir() 会更改传递给它的文件路径字符串?

问题描述

我正在尝试编写一个给定当前工作目录的函数,它将打印该目录的所有内容以及 cwd 中子目录中的内容。

void printDir(char *cwd)
{
  printf("file path after printdir call: %s\n",cwd);
  DIR *dirPtr = opendir(cwd);
  struct dirent *dirEnt;

  char *slash = "/";
  char *dot = ".";
  char *dotdot = "..";
  char *pathPrefix = malloc(sizeof(cwd) + sizeof(slash)+1);
  pathPrefix = strcat(cwd,slash);

  if (dirPtr != NULL)
  {
      while((dirEnt = readdir(dirPtr)) != NULL)
      {
          char *temp = dirEnt->d_name;
          if (strcmp(temp,dot) != 0 && strcmp(temp,dotdot) != 0)
          {

             char *tempFullPath = malloc(sizeof(pathPrefix) + sizeof(temp) + 1);
             tempFullPath = strcpy(tempFullPath, cwd);
             strcat(tempFullPath, temp);

             printf("file path before we try to openthedir: %s\n",tempFullPath);
             DIR *tempSubDirPtr = opendir(tempFullPath);

             printf("filePath after we try to open this shit: %s\n",tempFullPath2);
             if (tempSubDirPtr != NULL)
             {
                  printf("file path right before a recursive call: %s\n",tempFullPath);
                  closedir(tempSubDirPtr);
                  printDir(tempFullPath);
           }
           printf("%s\n",tempFullPath);
        }
    }
}
else
{

使用调试 printf() 的控制台输出是:

current working directory string after getcwd: /home/TTU/canorman/testUtil
file path after printdir call: /home/TTU/canorman/testUtil
file path before we try to openthedir: /home/TTU/canorman/testUtil/find.c
filePath after we try to open this shit: /home/TTU/canorman/testUtil/find.c
/home/TTU/canorman/testUtil/find.c
file path before we try to openthedir: /home/TTU/canorman/testUtil/find2.c
filePath after we try to open this shit: /home/TTU/canorman/testUtil/find2.c
/home/TTU/canorman/testUtil/find2.c
file path before we try to openthedir: /home/TTU/canorman/testUtil/find
filePath after we try to open this shit: /home/TTU/canorman/testUtil/find
/home/TTU/canorman/testUtil/find
file path before we try to openthedir: /home/TTU/canorman/testUtil/testDir
filePath after we try to open this shit: /home/TTU/canorman/testUA
file path right before a recursive call: /home/TTU/canorman/testUA
file path after printdir call: /home/TTU/canorman/testUA
Could not open specified working directory
/home/TTU/canorman/testUA/

因此,您可以在输出的最后几行中看到文件字符串来自

/home/TTU/canorman/testUtil/testDir

/home/TTU/canorman/testUA

我在 opendir(3) 手册页中找不到任何关于这种情况的信息。关于为什么会这样的任何想法。

标签: clinuxopendir

解决方案


这段代码肯定是错误的:

char *pathPrefix = malloc(sizeof(cwd) + sizeof(slash)+1);
pathPrefix = strcat(cwd,slash);

正如@Steve 和@William 所指出的,sizeof它们应用于指针而不是字符串,因此它每个分配4 或8 个字节(加一个),这不太可能是足够的。strlen(s)计算字符串中活动字符的数量;您必须自己为 NUL 字节添加 +1。

但更大的问题是使用strcat(),它将第二个字符串附加到第一个字符串的尾部,修改第一个字符串。这不是为您创建新的连接字符串,而是将其填充到新分配的(太小)内存中。

这应该表现得更好:

char *pathPrefix = malloc(strlen(cwd) + strlen(slash) + 1);
strcpy(pathPrefix, cwd);   // cwd goes to the start of the new buffer
strcat(pathPrefix, slash); // append the slash to the end of cwd

...然后在其余代码中进行类似的更改。

编辑:在进行此类工作时,最好对您不打算修改的const任何变量进行限定(从您的角度来看,字符串是只读的)。char *这样做会为您的代码添加有用的文档,并且编译器会警告您常见的错误。

例子:

void printDir(const char *cwd)
{
  ...
  const char *slash = "/";
  const char *dot   = ".";
  const char *dotdot = "..";

  ...

无论如何修改字符串文字都是不合法的,但如果cwd参数是 const 限定的,编译器会反对,strcat(cwd, slash)因为它知道第一个参数被写入。

这并没有真正改变代码的行为,但这是一个养成的好习惯。const是你的朋友。


推荐阅读