fgets вызывает зависание программы C при запуске из bash в Windows, но работает правильно при запуске из CMD или WSL - PullRequest
1 голос
/ 23 февраля 2020

Я следую учебному пособию «Создай свой собственный Лисп», чтобы научить себя C, и натолкнулся на странное поведение, связанное с fgets. Вот ссылка на главу, над которой я работаю: http://www.buildyourownlisp.com/chapter4_interactive_prompt#an_interactive_prompt

Код является простой основой для того, что в конечном итоге будет REPL. Он просто печатает некоторую информацию, а затем запускает al oop, который получает и печатает пользовательский ввод.

#include <stdio.h>

static char input[2048];

int main(int argc, char** argv) {
        puts("Brenlisp Version 0.0.0.0.1");
        puts("Press Ctrl+c to Exit\n");

        while (1) {
                fputs("brenlisp> ", stdout);
                fgets(input, 2048, stdin);
                fputs(input, stdout);
        }

        return 0;
}

Когда я запустил исполняемый файл с терминала Bash (Windows 10), программа запустилась но ничего не выводил на консоль и не принимал / печатал пользовательский ввод.

bschw@DESKTOP-92VUB1F MINGW64 ~/Projects/brenlisp
$ ./prompt.exe

Однако, когда я запускал исполняемый файл из CMD, приглашение выполнялось, как и ожидалось:

C:\Users\bschw\Projects\brenlisp>prompt.exe
BrenLisp Version 0.0.0.0.1
Press Ctrl+c to Exit

brenlisp> works fine
works fine
brenlisp> works fine
brenlisp> ^C
C:\Users\bschw\Projects\brenlisp>

Еще одна любопытная вещь: когда я запускаю программу на WSL, она не выводит строку «^ C» на консоль перед выходом:

bschw@DESKTOP-92VUB1F:/mnt/c/Users/bschw/Projects/brenlisp$ ./prompt.exe
BrenLisp Version 0.0.0.0.1
Press Ctrl+c to Exit

brenlisp> works
works
brenlisp> works
brenlisp> bschw@DESKTOP-92VUB1F:/mnt/c/Users/bschw/Projects/brenlisp$

Почему эти программы ведут себя по-разному в зависимости от из какой оболочки они запускаются? Как я мог заставить программу работать должным образом на Bash?

1 Ответ

0 голосов
/ 23 февраля 2020

Во многих реализациях стандартная библиотека C буферизирует выходные данные во внутренних буферах (*).

Часто для текстовых потоков она выполняет "строковую буферизацию" (буферы очищаются после обработки * 1003). *). Похоже, это ваш случай. Ваш вывод не содержит новой строки.

Чтобы принудительно очистить буферы, используйте fflush() для операций вывода.

printf("not a line");
fflush(stdout);             // force buffer emptying

printf("complete line\n");  // line-buffering poses no issue here

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

...