`fflush(stdin)` 失败

//  sigdemo1.c - show how a signal handler works.

// - run this and press Ctrl-C a few times

// 在第一次等待答复时,按下 Ctrl-C 只会出现 ^C 字符。

// 之后再按

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

#include <unistd.h>

extern void f(int);

int main(void) {

signal(SIGINT, f);

for (int i = 0; i < 5; ++i) {

printf("blah blah blah\n");

sleep(1);

}

return EXIT_SUCCESS;

}

extern void f(int signum) {

printf("\tInterrupted! OK to quit (y/n)?");

int c = getchar();

if (c == EOF || c == 'y') {

exit(EXIT_SUCCESS);

}

fflush(stdin);

}

在第一次发送 SIGINT 之后,输入 n 并回车,第二次中断时却在输出 Interrupted! OK to quit (y/n)? 之后就不接受输入,直接继续输出 blah blah blah, 第三次中断时才会接收输入。

怀疑 fflush(stdin) 没生效,求解。

回答:

之前的回答错了呜呜呜 QAQ

是这样子的,fflush(stdin) 在C标准里是行为未定义的,但是 glibc 说自己实现了这么个功能so。但是 glibc 2.20 骗人啦!它看看是不是存在未读取的数据,如果是,那么 lseek 回去!但很显然,连接到终端的 stdin 是不支持 lseek 的,所以就失败啦。glibc 只好忽略掉了。然后置位 _offset 字段为 _IO_pos_BAD加粗文字。

cint

_IO_new_file_sync (fp)

_IO_FILE *fp;

{

_IO_ssize_t delta;

int retval = 0;

/* char* ptr = cur_ptr(); */

if (fp->_IO_write_ptr > fp->_IO_write_base)

if (_IO_do_flush(fp)) return EOF;

delta = fp->_IO_read_ptr - fp->_IO_read_end;

if (delta != 0)

{

#ifdef TODO

if (_IO_in_backup (fp))

delta -= eGptr () - Gbase ();

#endif

_IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);

if (new_pos != (_IO_off64_t) EOF)

fp->_IO_read_end = fp->_IO_read_ptr;

#ifdef ESPIPE

else if (errno == ESPIPE)

; /* Ignore error from unseekable devices. */

#endif

else

retval = EOF;

}

if (retval != EOF)

fp->_offset = _IO_pos_BAD;

/* FIXME: Cleanup - can this be shared? */

/* setg(base(), ptr, ptr); */

return retval;

}

不知道这个是干什么的,反正 getchar 不理它:

cint

getchar (void)

{

int result;

_IO_acquire_lock (_IO_stdin);

result = _IO_getc_unlocked (_IO_stdin);

_IO_release_lock (_IO_stdin);

return result;

}

c#define _IO_getc_unlocked(_fp) \

(_IO_BE ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end, 0) \

? __uflow (_fp) : *(unsigned char *) (_fp)->_IO_read_ptr++)

PS: 在信号处理器里使用不可重入函数,是可能出问题的。

PPS: 不知道为什么,我这里在按第二次 Ctrl-C 时程序就被杀掉了。因为C库调用 rt_sigaction 时设置了 SA_RESETHAND 标志。

以上是 `fflush(stdin)` 失败 的全部内容, 来源链接: utcz.com/p/195430.html

回到顶部