Проблема с доступом к указателю на std::fstream

Не используя средства ввода-вывода С++ в течение длительного времени (вместо использования операций API C linux), я пытаюсь хотя бы ознакомиться с тем, как работает С++. Я работаю под Ubuntu 12.04., в соответствии с C++98, используя gcc -Wall, который компилируется без ошибок или предупреждений. Проблема возникла, когда мне нужно было создать новый файл, в который я сначала напишу, а затем прочитаю. Проблема заключается в следующем:

#include <fstream>

std::fstream::openmode o_M = std::fstream::in | std::fstream::out;
std::fstream::openmode o_M1 = o_M | std::fstream::trunc;

std::fstream* preproc;
preproc = new std::fstream(out_Name.c_str(), o_M1); // (1)
if ( !(preproc->good()) )
    errExit(1, "can't open file <%s>", out_Name.c_str());

preproc->put('c');
(*preproc) << "foo";  

Насколько я понимаю, это должно записать в файл "cfoo"; однако ничего не записывается, а файл создается с соответствующими разрешениями. Я перебрал множество итераций того, что может быть ложным (очистка потока, открытие в разных режимах, явное открытие файла, на который указывает файл;...), но безрезультатно. Кроме того, ранее в том же проекте я без проблем создаю и использую указатель fstream на существующий файл (используя тот же синтаксис, без квалификаторов openmode (конечно, я пытался не использовать openmodes и для файла выше)) - чтение только из существующего файла.

Когда я вместо этого использую доступ без указателя, как в

std::fstream TEST(out_Name.c_str(), o_M1); // (etc, ancillary changes)

все работает нормально.

Я смущен. Я, вероятно, не вижу леса за деревьями, и был бы благодарен за то, что кто-то указал, что мне не хватает.


person gnometorule    schedule 20.05.2014    source источник
comment
Итак, вы открываете два файловых потока для ввода/вывода с одним и тем же именем файла и задаетесь вопросом, почему... что? Почему использование двух буферизованных (подсказка) потоков ввода-вывода в одном и том же файле дает те результаты, которые вы видите?   -  person WhozCraig    schedule 21.05.2014
comment
ТЕСТ был добавлен только для отладки. В моем коде использовался указатель preproc, и я не мог писать в него с помощью ни одного из двух приведенных выше операторов ( ‹‹, put()). @WhozCraig. Однако я не понимаю, почему открытие одного и того же файла дважды должно быть проблемой - это не касается условий гонки или чего-то подобного. Если хотите, тот же вопрос с удалением всего, что связано с TEST.   -  person gnometorule    schedule 21.05.2014
comment
Если TEST вообще не должно быть там, то значительно поможет удаление его из внутренностей. поскольку он опубликован и описан, похоже, вы ожидаете записи через два разных потока открытых файлов в один и тот же файл для поддержания порядка операций записи и синхронизации. Надеюсь, понятно, как это можно увидеть таким образом. Таким образом, настоящая проблема заключается в том, что динамически открытый std::fstream, похоже, не записывает в ваш целевой файл, верно? TEST не имеет к этому никакого отношения?   -  person WhozCraig    schedule 21.05.2014
comment
@WhozCraig: да, и хорошее предложение. Я отредактирую исходный код в самый низ, когда вернусь домой (5 минут). Поскольку я так давно не работал с потоками C++ fstreams, я проверил, будет ли он работать, если я буду использовать доступ без указателя; так оно и было.   -  person gnometorule    schedule 21.05.2014
comment
в порядке. это, наверное, было бы лучше всего. Я собрал простой образец того, что, по моему мнению, вы делаете, и, похоже, он работает правильно, так что не конечно в чем проблема. Вывод фрагмента вставки cfoobar, как и ожидалось. В любом случае, удачной поездки.   -  person WhozCraig    schedule 21.05.2014
comment
@WhoCraig: это именно то, что я делаю, и это не работает на моей машине. (большое спасибо за то, что написали это, и см. выше изменения, основанные на вашем предложении - может быть, вы видите тип или я не вижу)   -  person gnometorule    schedule 21.05.2014
comment
Может быть, dtor потока сбросит и закроет, что не вызывается в версии указателя?   -  person Peter - Reinstate Monica    schedule 21.05.2014
comment
@PeterSchneider: есть предложения, что попробовать?   -  person gnometorule    schedule 21.05.2014
comment
@WhozCraig: Вы поняли это в своем коде: по какой-то причине мне нужно сбросить(), когда я закончу писать (хотя я вижу, насколько это логично, в книге Страуструпа нет того, кого я вытащил для сравнения после того, как я заметил, что это заставило его работать ...). Я предлагаю вам опубликовать что-то вроде ответа, чтобы я мог принять это? Я мог видеть, как кто-то другой может столкнуться с проблемой и найти это ценным.   -  person gnometorule    schedule 21.05.2014
comment
@PeterSchneider: на самом деле, ваше предложение тоже работает. Было бы хорошо, если бы один из вас двоих хотя бы написал ответ, может быть (в моем коде указатель будет глобальным, удаленным намного позже, поэтому вместо этого я должен использовать маршрут flush(), но он работает в принципе).   -  person gnometorule    schedule 21.05.2014


Ответы (1)


Вы не выполняете flushing, closeing или deleteing поток, поэтому буфер не сбрасывается. Ваша версия стека работает, потому что поток сбрасывается и закрывается, когда объект уничтожается после того, как он выходит из области видимости.

Либо сбросить поток, например, вызвав flush или close, либо удалить указатель с помощью delete preproc;. Еще лучше не использовать объекты, размещенные в куче, если это возможно.

Вы также можете настроить fstream для работы в небуферизованном режиме, вызвав

preproc->rdbuf()->pubsetbuf(NULL, 0); // nullptr for C++11

сразу после открытия потока, хотя вряд ли это то, что вам нужно.

Если вам необходимо использовать кучу, с С++ 11 вы можете воспользоваться преимуществами std::unique_ptr/std::shared_ptr. Если вы застряли с С++ 98, есть также std::auto_ptr (предостережение).

person user657267    schedule 21.05.2014
comment
Да, спасибо; после обсуждения выше (и того, что вы пишете) теперь я вижу, что происходит (я не смогу использовать C++11 для этого проекта; и - пока я не рефакторинг своего кода - я могу не используйте указатель, поскольку в настоящее время он является глобальным). - person gnometorule; 21.05.2014
comment
@gnometorule В этом случае либо close, либо flush поток. - person user657267; 21.05.2014
comment
+1, включая использование интеллектуальных указателей, нулевой буфер и т. д. Все это и куча муки. хорошая запись. - person WhozCraig; 21.05.2014
comment
@WhozCraig bowel of grits звучит не слишком аппетитно :D - person user657267; 21.05.2014