【问题标题】:Using POSIX glob() function, gl_pathv is returning NULL — how do I get the file name?使用 POSIX glob() 函数,gl_pathv 返回 NULL — 我如何获取文件名?
【发布时间】:2020-11-23 13:03:33
【问题描述】:

我正在尝试获取以.c 结尾的第一个文件名。
我的目录中有一个file.c,我希望它会被打印出来。但是,(null) 不断被打印出来,我不明白为什么。

这是我当前的代码:

#include <glob.h>
#include <stddef.h>
#include <stdio.h>

int main(int argc, char **argv) {

    glob_t buf;
    
    buf.gl_offs = 2;
    
    glob("*.c", GLOB_DOOFFS, NULL, &buf);
    
    printf("%ld", buf.gl_pathc);
    printf("%s", buf.gl_pathv[0]);

    return 0;
}

谁能告诉我出了什么问题?

【问题讨论】:

标签: c linux file glob


【解决方案1】:

您设置了buf.gl_offs = 2;,并将GLOB_DOOFFS 传递给glob(),因此您告诉它在gl_argv 指针列表的开头留下两个未使用的插槽;它按照你的要求做了,这些插槽是 NULL 指针。空槽背后的想法是,代码可能想要添加一个命令名称,并且可能需要在这些槽所在的位置添加一些参数,例如,buf.gl_pathv 可以传递给execv()glob() 的 POSIX 规范说“最后一个路径名之后的第一个指针应该是一个空指针”,这当然是 execv() 所要求的。

用途:

#include <glob.h>
#include <stddef.h>
#include <stdio.h>

int main(void)
{
    glob_t buf;

    buf.gl_offs = 2;

    if (glob("*.c", GLOB_DOOFFS, NULL, &buf) != 0)
    {
        fprintf(stderr, "glob() failed\n");
        return 0;
    }

    printf("%ld\n", buf.gl_pathc);
    printf("%s\n", buf.gl_pathv[0]);

    for (size_t i = 0; i < buf.gl_pathc + buf.gl_offs + 1; i++)
    {
        printf("%zu: [%s]\n", i,
               (buf.gl_pathv[i] == NULL ? "<null>" : buf.gl_pathv[i]));
    }

    globfree(&buf);

    return 0;
}

这段代码是懒惰的;它依靠printf("%s\n", buf.gl_pathv[0]); 在将空指针作为字符串传递时不会崩溃(原始代码)。这不是 C 标准所要求的。主循环显示了你应该为可靠的代码做什么——你应该在调用printf()之前映射空指针。

在我的机器上,它产生了:

28
(null)
0: [<null>]
1: [<null>]
2: [alarm47.c]
3: [book41.c]
4: [checkeuid.c]
5: [dec37.c]
6: [glob61.c]
7: [grid17.c]
8: [hms37.c]
9: [int89.c]
10: [ll11.c]
11: [log41.c]
12: [pipe17.c]
13: [pipe29.c]
14: [pipe31.c]
15: [pipe43.c]
16: [pipe73.c]
17: [pipe83.c]
18: [prtree37.c]
19: [rc61.c]
20: [rep31.c]
21: [rn83.c]
22: [rn89.c]
23: [sh31.c]
24: [sh47.c]
25: [sh67.c]
26: [sh71.c]
27: [sh79.c]
28: [sh97.c]
29: [test-strsep.c]
30: [<null>]

注意buf.gl_pathc 中的计数不包括buf.gl_offs 指定的空槽或终止空指针。我不得不检查目录中的文件名列表——碰巧有 28 个.c 文件。 (早期版本的代码没有遍历名称列表。)

JFTR:我在运行 macOS Mojave 10.14.6 的 Mac 上进行了测试。

【讨论】:

  • 非常感谢您的详细回答。这肯定需要很长时间才能回答。我运行了代码,它给出了一个段错误(不确定这是否是故意的),但至少现在我明白发生了什么。另外,据我了解,设置buf.gl_offs = 0; 也很好。只要我只想要文件名。
  • 你可能会从马虎的printf() 中得到 seg 错误,但你确实说你看到了(null)。您是否能够准确追踪崩溃的原因?是的,如果您只想要名称,将 gl_offs 设置为 0 就可以了;你也可以省略GL_DOOFFS(并将0作为标志参数传递给glob())。至于时间——基本的答案用不了多久,但打磨却需要一些时间。 OTOH,作为一种学习体验,这对我很有用——我需要使用 glob()(或者可能是 wordexp())来处理我需要更改以处理 globbing 的程序。
  • 是的,我想当我尝试使用 for 循环时出现溢出。这个问题很容易解决。 glob() 真的很方便,这是毫无疑问的 :)
  • 并且,为了明确起见:上面的程序不应该崩溃,除非printf() 在字符串的空指针上崩溃。
猜你喜欢
  • 2017-12-04
  • 2017-10-28
  • 2012-12-31
  • 2015-09-14
  • 2010-12-04
  • 2011-07-02
  • 2023-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多