为什么getcwd因errno ENOENT而失败

时间:2017-08-24 12:25:55

标签: c++ centos ubuntu-16.04 getcwd

我正在使用getcwd函数来检索应用程序的当前工作目录。 在某些情况下,它失败了,错误是ENOENT。我从不同的线程调用getcwd,但是连续地,有时我面对ENOENT,但我不知道为什么。 上面的链接表示ENOENT表示“当前工作目录已取消链接”。但目录存在。

以下是我使用的功能片段:

更新:根据@Aganju和@molbdnilo的建议更新代码:

std::string get_working_dir()
{
    char buf[PATH_MAX];
    memset(buf, 0, sizeof(buf));
    char * result = getcwd(buf, sizeof(buf));
    std::string working_path = buf;
    // Check for possible errors.
    if (result == NULL)
    {        
        switch (errno)
        {
            case EACCES:
                break;
            case EFAULT:
                break;
            case EINVAL:
                break;
            case ENAMETOOLONG:
                break;
            case ENOENT:
            {
                if (working_path.empty())
                {
                    const char* pwd = getenv("PWD");
                    working_path = (pwd) ? pwd : "";
                }
                break;
            }
            case ERANGE:
                break;
            default:
                break;
        }
        return working_path;
    }
}

如果我面对ENOENT,我会检索“PWD”环境变量,因为我在CentOS 5.11和Ubuntu 16.04上工作,当CentOS上的getcwd失败时,它返回一个空缓冲区。

更新:

我注意到来自主线程的调用没有失败,但是当我从另一个线程调用该函数时它失败并且errno是ENOENT。

2 个答案:

答案 0 :(得分:2)

molbdnilo所述,您需要先检查返回值。

您链接到州的手册:

  

[...]失败时,这些函数返回NULL,并且errno设置为   表示错误。[...]

换句话说,如果没有失败,errno 设置,并且包含之前发生的任何调用所包含的内容,可能很长之前的时间,在这种情况下没有意义。

使用char * result = getcwd(buf, sizeof(buf));之类的内容,然后检查if (result == NULL) { switch (errno) ...

答案 1 :(得分:1)

这可能发生在以下情况中,我们可以使用shell脚本语法通过多进程序列图来说明:

process A                     process B
$ cd ~                        $ cd ~
user $ mkdir foo            
user $ cd foo
                              user $ rm -rf foo              
user/foo $ pwd
/home/user/foo
user/foo $ cd .
cd: error retrieving current
directory: getcwd: cannot access
parent directories: No such file or directory

类Unix操作系统中的每个进程都有一个当前工作目录,它保存对文件系统中对象的引用。在进程删除当前目录之前,该对象不能被回收为可用空间。

上面,流程A继续保留曾经 ~/foo的目录。目录结构中不再存在路径,但目录对象仍然存在。

getcwd系统调用意识到这一点:它看到调用进程的当前工作目录没有链接到目录结构,因此没有路径,因此报告错误。

pwd shell命令有效,因为它只是在不调用getcwd的情况下反弹shell知道的一段数据;但是当我们尝试cd .时,会发生错误(在GNU / Linux系统上使用Bash重现;结果可能会有所不同)。