2016-03-15 1 views
2

Учитывая boost::filesystem::path p, возможно ли иметь boost::filesystem::is_regular_file(p) == true и std::ifstream(p.c_str()).is_open() == false в то же время? Если да, в какой ситуации?Какая у меня гарантия после is_regular_file?

Контекст сочинительстве утверждают для функции сравнения:

bool identical_files(const boost::filesystem::path& p1, const boost::filesystem::path& p2) 
{ 
    assert(boost::filesystem::is_regular_file(p1)); 
    assert(boost::filesystem::is_regular_file(p2)); 
    std::ifstream f1(p1.c_str()); 
    assert(f1.is_open()); // IS THIS REDUNDANT ??? 
    std::ifstream f2(p2.c_str()); 
    assert(f2.is_open()); 
    // ... 
    // ... 
    // ... 
} 
+2

Я нахожу, что для большинства операций с файловой системой лучше лучше просить прощение, чем разрешить * парадигма (в отличие от парадигмы * перед вами). В вашем случае это означает, что 'is_regular_file (p1)' является избыточной проверкой, потому что в любом случае вам всегда понадобится 'f1.is_open()'. – Escualo

+0

Но 'f1.is_open()' is 'true', когда' p1' является каталогом. – Caduchon

+2

Затем сначала сделайте 'f1.is_open()', а затем выполните 'is_regular_file()', вы можете воспользоваться коротким замыканием: 'if (f1.is_open() и f1.is_regular_file())' – Escualo

ответ

4

Единственная гарантия у вас есть то, что в момент вызова, путь был обычный файл. Поскольку файловая система является неявным условием гонки, звонок между boost::filesystem::is_regular_file(p1) и std::ifstream f1(p1.c_str()) может фактически иметь отношение к двум различным объектам .

Рассмотрим сценарий:

  • Процесс 1 вызовов boost::filesystem::is_regular_file(p1), преуспевает и определяет, что это файл "нормальный"
  • Process 2 удаляет путь, на который указывает p1
  • процесса 1 вызовов std::ifstream f1(p1.c_str()), и не в состоянии открыть файл

Вы видите здесь состояние гонки?

+5

Он также может выйти из строя, если процесс не имеет разрешения на доступ к целевому файлу; файл будет существовать, но его открытие не удастся. Параметр 'is_regular_file' также исключает фиолетовые и символьные устройства. –

+1

Спасибо за этот конкретный пример. В моем случае я предпочитаю игнорировать проблемы с оценкой, потому что он, вероятно, никогда не используется в многопоточном контексте. Мой вопрос касается примерно того же файла, без участия thrid-party, пытающегося захватить мой код. ;-) Но ответ полковника Тридцать два уместен в моем случае. – Caduchon