2017-08-24 103 views
0

我使用getcwd函数来检索我的应用程序的当前工作目录。 在某些情况下,它失败并且errno是ENOENT。我从不同的线程调用getcwd,但是连续地,有时我会面对ENOENT,但我不知道为什么。 上面的链接指出ENOENT意味着“当前工作目录已被取消链接”。但目录存在。为什么getcwd失败errno ENOENT

这里是我使用的功能的一个片段:

UPDATE:代码与@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失败时,它返回一个空的缓冲区。

UPDATE:

我已经注意到了,从主线程调用不会失败,但是当我调用该函数从另一个线程失败和错误号是ENOENT。

+0

在您的进程中运行'strace',可能带有'-f'标志,并观察哪个系统调用返回'ENOENT'。这将是你的第一个线索,可能会发生什么。 –

+3

您需要先检查'getcwd'的返回值。 'errno'没有意义,除非'getcwd'返回一个空指针。 – molbdnilo

+0

我检查了NULL,因为你和@Aganju推荐。在CentOS 5上,'getcwd'返回NULL,errno是ENOENT。我要更新示例代码。 我注意到的一件事是,由于我的应用程序是多线程的,因ENOENT而失败的调用是那些不从主线程调用的调用。 – rboc

回答

2

由于molbdnilo表示,您需要先检查返回值。

手动链接到规定:

[...]如果失败,这些函数返回NULL,并设置errno以 指示错误[...]

换句话说,如果存在没有失败,errno而不是集合,并且包含从之前发生的任何呼叫(可能很长时间以前)中所包含的任何内容,在此上下文中没有意义。

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

+0

我按照你的建议检查了NULL。 在CentOS 5上getcwd返回NULL,errno是ENOENT。我已经更新了这个问题。 – rboc

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基准的;但是当我们尝试cd .时,会发生错误(在GNU/Linux系统上使用Bash复制;结果可能会有所不同)。

+0

我的应用程序是单进程但多线程的。无论如何,这可能会发生吗?线程应该共享工作目录。 – rboc

+0

这是'chdir'系统调用在整个进程中的副作用是POSIX的一个错误特性。实际上,多线程进程应该在启动时建立一个工作目录,而不是再次触及它。而且,隐含地调用'chdir'的函数必须像'nftw'那样避免。 – Kaz