Ошибка ввода-вывода при записи на ненадежный диск в C ++ - PullRequest
1 голос
/ 04 ноября 2011

Представьте, что у вас в C ++ есть следующее:

ofstream myfile;
myfile.open (argv[1]);

if (myfile.is_open()){
 for(int n=0;n<=10;n++){
     myfile << "index="<<n<<endl;
     sleep(1);
 }
}else{
cerr << "Unable to open file";
}

myfile.close();

И во время записи диск или носитель, на который вы пишете, становится недоступным, но возвращается к функции close (), так что у вас отсутствуют данные вмежду.Или представьте, что вы записываете на флэш-накопитель USB, а устройство извлекается и вставляется в процессе записи.Как вы можете обнаружить это?Я попытался проверить помещение записи в try {} catch, flags (), rdstate (), как вы ее называете, но пока ни одна из них, похоже, не работает.

Ответы [ 4 ]

1 голос
/ 04 ноября 2011

ИМХО можно попробовать:

  1. Использование ios: исключения
  2. Использовать низкоуровневые взаимодействия с ОС
  3. Убедитесь, что ввод-вывод прошел успешно (если 1 и 2 не работают)
1 голос
/ 04 ноября 2011

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

Если вы действительно хотите обнаружить ненадежный жесткий диск, вам, вероятно, потребуется кодировать на гораздо более низкий уровень, например написать свой собственный аппаратный драйвер.

0 голосов
/ 04 ноября 2011
for(int n=0;n<=10;n++){
    if (!(myfile << "index="<<n<<endl))
        throw std::runtime_error("WRITE FAILED")
    sleep(1);
}

Если по какой-либо причине происходит сбой std::ostream, он устанавливает бит состояния, который проверяется, тогда std::stream находится в логическом контексте.Это так же, как вы проверяете, правильно ли std::istream считывает данные в переменную.

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

[Редактировать] Согласно http://msdn.microsoft.com/en-us/library/17618685(v=VS.100).aspx, вы можете принудительно выполнить сброс с помощью _commit, если у вас есть дескриптор файла.Я не могу найти такую ​​гарантию для std::ostream s.

0 голосов
/ 04 ноября 2011

Я не уверен, что это будет охватывать ваш сценарий (удаление середины записи USB-накопителя), но вы можете попробовать включить исключения в потоке:

myfile.exceptions(ios::failbit | ios::badbit);

По моему опыту, iostreams делают«отличная» работа по выявлению ошибок и их типов.

...