Я использую getcwd функция для получения текущего рабочего каталога моего приложения.
В некоторых случаях это терпит неудачу, и errno является 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, а когда getcwd дает сбой в CentOS, он возвращает пустой буфер.
ОБНОВИТЬ:
Я заметил, что вызов из основного потока не завершается ошибкой, но когда я вызываю функцию из другого потока, она завершается неудачно, и errno является ENOENT.
Как molbdnilo сказал, что вы должны проверить возвращаемое значение в первую очередь.
В руководстве вы ссылаетесь на штаты:
[…] При сбое эти функции возвращают NULL, а errno устанавливается в
указать ошибку. […]
Другими словами, если есть нет недостаточность, errno
является не установить, и содержит все, что он содержал от любого вызова, случившегося раньше, может быть, задолго до этого, что не имеет смысла в этом контексте.
Используйте что-то вроде char * result = getcwd(buf, sizeof(buf));
, а затем проверьте if (result == NULL) { switch (errno) ...
, так далее.
Это может произойти в следующей ситуации, которую мы можем проиллюстрировать на диаграмме последовательности из нескольких процессов, используя синтаксис сценария оболочки:
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-подобной операционной системе имеет текущий рабочий каталог, который содержит ссылку на объект в файловой системе. Этот объект не может быть возвращен как свободное место, пока процесс не удалит этот текущий каталог.
Выше процесс А продолжает удерживать каталог, который раньше был ~/foo
, Тот дорожка больше не существует в структуре каталогов, но каталог объект продолжает существовать.
getcwd
Системный вызов понимает это: он видит, что текущий рабочий каталог вызывающего процесса не связан с структурой каталогов и, следовательно, не имеет пути, поэтому он сообщает об ошибке.
pwd
Команда оболочки работает, потому что она просто извергает часть данных, о которой оболочка знает без вызова getcwd
; но когда мы пытаемся cd .
возникает ошибка (воспроизводится с помощью Bash в системе GNU / Linux; результаты могут отличаться).