Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.12.2011, 02:51   #11
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
PPPS: немного подумав, решил что возвращается окошко по причине того что старый буфер то жив, и cin его возвращает обратно.
вы же не перенаправили stdin.
Этого не достаточно? Но это кстати, и не спасает.
Код:
void Redirect_Stdin(); //перенаправление стандартного потока ввода
_Bers вне форума Ответить с цитированием
Старый 02.01.2012, 16:34   #12
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Лекарство было найдено!

Если кому интересно, то проблема была вот в чем:

Немного лирики: Новый год прошёл в напряженной работе по поиску решения проблемы. Моя девушка начала волноваться, переживать, думая что у нас что-то не то. Девушкам же невозможно объяснить, что время - релизиться, а код крэшэт всю систему с синим экраном смерти.

Ближе к 5 утра, я лежал в постели, смотрел в потолок, размышляя об IO-потоках.
Как бы там нибыло, а все дороги ведут в Рим - к WINAPI. Не важно, явно ли вызывает WINAPI программист, или это делается в недрах crt библиотеки с++.
Важно, что по сути... стоп... назад...

Ещё раз: явно ли вызывает WINAPI программист, или это делается в недрах crt библиотеки с++.

Вот здесь и крылась разгадка. Сейчас 16 на моих часах. Я опробовал лекарство, и это сработало. Итак, вот пример работающего кода:

Код:
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>


void RedirectIOToConsole(); //подружим каут с новым консольным буфером
void Test();  //тестирование работоспособности кода. 
                  //Если все хорошо, то вывод текста должен идти в консоль у которой 
                  //нет вертикальной полосы прокрутки. 
                  //Не должно быть самопроизвольных переключений буфера
                  //вывода на оригинальный. Тестирование предполагает ввод-вывод 
                  //средствами сишных потоков, и приплюснутых

int main()
{
    HANDLE FirstScreenBuffer= CreateConsoleScreenBuffer(
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ|FILE_SHARE_WRITE,  //<--- проблема была вот здесь

            //средства ввода-вывода crt юзают буфер ввода черт знает как.
            //и происходит это из другого процесса. Поэтому, буфер должен быть 
            //шаристым

            NULL,  
            CONSOLE_TEXTMODE_BUFFER,
            NULL  );
    SetConsoleActiveScreenBuffer(FirstScreenBuffer);

    SetStdHandle(STD_OUTPUT_HANDLE, FirstScreenBuffer);

    RedirectIOToConsole();

    Test();
}


void RedirectIOToConsole()
{
    int hConHandle; long lStdHandle; FILE *fp;

    // redirect unbuffered STDOUT to the console
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "w" );    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );

    std::ios::sync_with_stdio(); //подружим сишные потоки с приплюснутыми
}

void Test()
{
    using namespace std;

    int iVar;
    fprintf(stdout, "Test output to stdout\n");
    fprintf(stderr, "Test output to stderr\n");
    fprintf(stdout, "Enter an integer to test stdin: ");
    scanf("%d", &iVar);
    printf("You entered %d\n", iVar);

    //test iostreams

    cout << "Test output to cout" << endl;
    cerr << "Test output to cerr" << endl;
    clog << "Test output to clog" << endl;
    cout << "Enter an integer to test cin: ";
    cin >> iVar;
    cout << "You entered " << iVar << endl;
}
Фокус был в том, что раньше я создавал не_шаристый буфер. А монопольный.
(и кстати, я не вполне понимал, зачем вообще создавать шаристые буфера, если нет причин наследоваться от родительских процессов)
Доступ к нему имел только один родительский процесс.

Однако чорт его знает, кто и как к нему обращается, через std::cin Или через stdin, когда пытается сделать эхо-отражение.

В действительности, библиотечные функции самого языка(как и функции WINAPI) - лишь вершина айсберга, этой поистине нетривиальной технологии "ввода-вывода". А главные боевые действия осуществляющие ввод-вывод запрятаны очень глубоко в недрах операционной системы. Вывод данных через новый буфер осуществляется средствами самой ОСи. И нужно было быть готовым к тому, что вывод данных в буфер консоли будет осуществлен из какого то вообще левого процесса.

Единственное, что осталось не понятным, это почему ОС не пофиксила факт монопольного использования буфера вывода консоли, при попытки поюзать его.
Почему пользовательское приложение, используя винапи согласно документации умыдрилось уронить всю систему?

Полагаю, это действительно баг разработчиков Windows, и не является проблемой пользовательского приложения.

Последний раз редактировалось _Bers; 02.01.2012 в 18:31.
_Bers вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Баг или фича? (programmersforum) Сtrl О форуме и сайтах клуба 7 05.09.2011 21:20
Потоки. Использование стандартного ввода–вывода. Lazy_Bitch Общие вопросы C/C++ 1 05.05.2010 12:15
Перенаправление стандартного ввода/вывода в файл Роман Радер Общие вопросы C/C++ 1 09.01.2010 18:34
Как сделать запрет ввода букв в поле для ввода input zvezda_t PHP 1 27.12.2009 22:02
Баг Excel или я туплю? Raf_19 Microsoft Office Excel 5 06.08.2008 16:39