Возвращает ли fopen указатель NULL, если файл уже открыт?

Я предполагал, что fopen возвращает указатель NULL, если файл уже открыт. Но похоже, что fopen не возвращает NULL, если файл уже открыт в режиме "w". Ниже приведен код, который я использовал, чтобы попробовать это, и я не получаю никаких ошибок. Я пробовал использовать компиляторы mingw32 и TDM-GCC-64. Если не ошибаюсь, C++ выдает ошибку, если файл уже открыт.

#include<stdio.h>

int main()
{
    FILE *fp1, *fp2;
    
    fp1 = fopen("file1.txt", "w");
    fp2 = fopen("file1.txt", "w");
    
    if (fp2 == NULL)
    {
        printf("Error in opening file\n");
        return(0);
    }
    
    // Edit: added following code to check the behavior if write operation
    // is performed simultaneously
    
    fputc('A', fp1);
    fputc('M', fp1);
    fputc('S', fp1);
    fputc('B', fp2);
    
    fclose(fp1);
    fclose(fp2);
    
    return 0;
}

Обновлено: добавлен дополнительный код для записи данных в fp1 и fp2 и просмотра поведения. Если выполняется, file1.txt содержит данные BMS и кажется правильным поведением, а fp1 и fp2 перемещаются независимо, как и ожидалось. Сначала AMS записывается с использованием fp1, затем A заменяется на B с использованием fp2, и конечный результат - BMS.

Так что же происходит в опубликованном коде?

Lasse V. Karlsen 01.05.2018 11:27

@Rajesh Речь идет о совместном использовании файлов, в Windows, если ваша реализация lib вызывает _fsopen с SH_DENYNO (например), тогда другая программа (или та же самая ...) может открывать файл несколько раз (также для записи). Что произойдет, зависит как от реализации, так и от базовой ОС (одновременная запись не так проста, по крайней мере, в Windows). Обратите внимание, однако, что fopen() по умолчанию предполагает совместное использование, потому что обычно * nix OS использует другие примитивы синхронизации (см. fcntl())

Adriano Repetti 01.05.2018 11:30

Cit: В большинстве реализаций библиотек для переменной errno также устанавливается системный код ошибки при сбое.

Jacek Cz 01.05.2018 11:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
2 439
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Согласно стандарту C (7.19.3.8) он определяется реализацией:

Functions that open additional (nontemporary) files require a file name, which is a string. The rules for composing valid file names are implementation-defined. Whether the same file can be simultaneously open multiple times is also implementation-defined.

Кроме того, это не рекомендуется по другим причинам, см., Например, Рекомендация FIO24-C стандарта кодирования SEI CERT C:

Some implementations do not allow multiple copies of the same file to be open at the same time. Consequently, portable code cannot depend on what will happen if this rule is violated. Even on implementations that do not outright fail to open an already-opened file, a TOCTOU (time-of-check, time-of-use) race condition exists in which the second open could operate on a different file from the first due to the file being moved or deleted (see FIO45-C. Avoid TOCTOU race conditions while accessing files for more details on TOCTOU race conditions).

Я добавил дополнительный код и отредактировал сообщение. Если мы попытаемся писать одновременно с использованием обоих файловых указателей, оба будут записаны, и файловые указатели будут обрабатываться независимо, и я думаю, что это правильное поведение.

Rajesh 01.05.2018 12:55

Другие вопросы по теме