2013-11-23 3 views
0

я пытался скомпилировать и запустить C код, который имеет следующие строки:Почему я не могу «freopen» «tmpfile»?

FILE *preproc_producer = NULL; 
preproc_producer = tmpfile(); 
// preproc_producer is not NULL here 
preproc_producer = freopen(NULL, "r+", preproc_producer); 
// preproc_producer is NULL here 

Однако при выполнении кода, preproc_producer заканчивает NULL, и код ошибки Stale NFS file handle

  1. Что такое вопрос с вышеуказанным кодом?

  2. Какова цель звонка freopen? Я прокомментировал строку freopen, и остальная часть программы, похоже, работает.

Я использую GCC 4.7.2, работает Ubuntu 64 12.04 внутри Docker 0.6.7 Linux-контейнер. Вышеприведенный код работает вне контейнера Docker.

Обновление: Трассирование свалка:

stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0 
gettimeofday({1385247432, 199732}, NULL) = 0 
getpid()        = 127 
open("/tmp/tmpf9l14HD", O_RDWR|O_CREAT|O_EXCL, 0600) = 3 
unlink("/tmp/tmpf9l14HD")    = 0 
fcntl(3, F_GETFL)      = 0x8002 (flags O_RDWR|O_LARGEFILE) 
brk(0)         = 0xc94000 
brk(0xcb5000)       = 0xcb5000 
fstat(3, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7afb9d0000 
lseek(3, 0, SEEK_CUR)     = 0 
lstat("/proc/self/fd/3", {st_mode=S_IFLNK|0700, st_size=64, ...}) = 0 
munmap(0x7f7afb9d0000, 4096)   = 0 
open("/proc/self/fd/3", O_RDWR)   = -1 ESTALE (Stale NFS file handle) 
+1

NULL означает отказ, в противном случае возвращаемый указатель потока уже «открыт» ... http://www.cplusplus.com/reference/cstdio/tmpfile/ –

+0

запустите свою программу в 'strace' и посмотрите, что произойдет. Я бы не ожидал, что это сработает, если freopen() должен закрыть файл, чтобы изменить режим доступа, поскольку tmpfile() удаляется, когда он закрыт. – nos

+1

Взгляните на спецификацию POSIX для ['freopen()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/freopen.html). Вы должны установить 'errno = 0;' перед тем, как сделать вызов, и затем осмотреть 'errno', когда повторное открытие не сможет определить, почему это не удалось. Поверхностно, нет причин, по которым код не должен работать; В равной степени нет очевидной причины, по которой вам понадобится 'freopen()' в первую очередь. –

ответ

3

От стандарта C99:

freopen функция открывает файл, имя которого является строка, на которую указывает имя файла и связывает поток указал к потоку с ним. Аргумент mode используется только , как в функции fopen.

Если имя файла является пустой указатель, freopen функция пытается изменить режим потока от указанного режима, как если имя текущего файла, связанного с был использован поток. Определяется реализация, какие изменения режима разрешены ( ) и при каких обстоятельствах.

Так что, возможно, кто написал этот код означал, чтобы изменить временный файл открытого режим от w+b к r+ (которая в основном сводится изменить поток в текстовом режиме). К сожалению, кажется, что в вашей реализации невозможно изменить открытый режим временного файла таким образом.

Я полагаю, что это может исходить из того факта, что закрытие временного файла и удаляет его, но он также может быть, что glibc реализация freopen не поддерживает изменения режима в freopen (страница руководства даже не говоря уже о возможности передать NULL в качестве первого аргумента).

+0

действительно. freopen() в glibc-документах, что он закрывает существующий поток. Это означает, что для tmpfile() файл также удаляется. – nos

+0

Я добавил strace. Ошибка выполняется на 'open ("/proc/self/fd/3 ", O_RDWR)'.Возможно, это проблема файловой системы? –

Смежные вопросы