2015-11-24 31 views
9

Nie można znaleźć żadnego odwołania do określonego zachowania fputc(), gdy strumień został utworzony za pomocą fopen("/some/path", "r").Zachowanie funkcji fputc() dla strumienia otwartego w trybie odczytu

Przeszukałem plik C11 Draft n1570 pdf, szukając odniesienia bez powodzenia, specyfikacja funkcji fopen() mówi o przekazywaniu nieznanych znaków jako parametr trybu, który jest niezdefiniowanym zachowaniem. Ale nie mówi nic o kolejnym IO w stworzonym strumieniu.

To określenie fwrite() funkcja

7.21.8.2 Funkcja fwrite

Streszczenie

  1. #include <stdio.h> 
    size_t fwrite(const void * restrict ptr, 
        size_t size, size_t nmemb, FILE * restrict stream); 
    

Opis

  1. Funkcja fwrite zapisuje z matrycy wskazywanego przez ptr, do nmemb elementów, których wielkość jest określona przez size, do strumienia wskazywanego przez stream . Dla każdego obiektu wywołania rozmiaru są wprowadzane do funkcji fputc, przyjmując wartości (w kolejności) z tablicy dokładnie pokrywającej obiekt. Wskaźnik pozycji pliku dla strumienia (jeśli został zdefiniowany) jest przesuwany o liczbę pomyślnie wpisanych znaków. Jeśli wystąpi błąd, wynikowa wartość wskaźnika położenia pliku dla strumienia jest nieokreślona.

Zwraca

  1. fwrite funkcja zwraca liczbę elementów z powodzeniem napisane, którego będzie mniejsza niż nmemb tylko wtedy, gdy błąd zapisu spotyka. Jeśli size lub nmemb ma wartość zero, fwrite zwraca zero, a stan strumienia pozostaje niezmieniony.

To prowadzi nas do funkcji fputc(), więc

7.21.7.3 fputc funkcja

Streszczenie

  1. #include <stdio.h> 
    int fputc(int c, FILE *stream); 
    

Opis

  1. Funkcja fputc zapisuje się znak określony przez c (przekształcony na unsigned char) na strumień wyjściowy wskazywany przez stream, w położeniu wskazanym przez skojarzony wskaźnik położenia pliku dla strumienia (jeśli został zdefiniowany) i odpowiednio przesuwa wskaźnik. Jeśli plik nie obsługuje żądań pozycjonowania lub jeśli strumień został otwarty w trybie dołączania, znak jest dołączany do strumienia wyjściowego.

Zwraca

  1. Funkcja fputc zwraca znak pisemnej. Jeśli wystąpi błąd zapisu, wskaźnik błędu dla strumienia jest ustawiony i fputc zwraca EOF.

Jak widać, nie ma wyjaśnienia sytuacji, której się niepokoję.

+1

To prawdopodobnie UB. –

+3

Jeśli nie jest to objęte słowem "zaniechanie" w rozdziale 4 zdanie 2 ("Niezdefiniowane zachowanie jest inaczej wskazane w niniejszym międzynarodowym standardzie słowami" niezdefiniowane zachowanie "lub przez pominięcie jakiejkolwiek wyraźnej definicji zachowania."), to może być niedociągnięcie w definicji plików i strumieni (7.21.1, 7.21.2). Nie widzę żadnej istotnej definicji dla słowa "otwórz plik do odczytu" 'fopen', które określałoby zachowanie się operacji nie czytających względem strumienia wynikowego. Sądzę, że zachowanie * powinno * polegać na tym, że liczą się jako błędy zapisu (patrz zacytowane punkty 3). –

+0

@iharob * ... Zdarzyło mi się, że przypadkowo fprintf() do strumienia otwartego z "r" zadziałało ... * Ciekaw jestem co do szczegółów, gdzie to "działało". Myślę, że podstawowe wywołanie 'open()' (lub równoważne) byłoby wykonane z flagami dopasowanymi do 'fopen ("/some/path "," r ");'. –

Odpowiedz

5

Jest to niezdefiniowane zachowanie, standard nie definiuje zachowania, jeśli nie jest strumieniem wyjściowym. To jest z sekcji 4 Zgodności, który mówi (nacisk kopalni):

Jeśli „” powinien „” lub „” nie ma „” wymóg, który pojawia się poza ograniczeniem lub wykonawczego przymusu jest naruszone, zachowanie jest niezdefiniowane. Niezdefiniowane zachowanie jest inaczej oznaczone w niniejszym standardzie międzynarodowym za pomocą słów "nieokreślone zachowanie" lub przez pominięcie dowolnej wyraźnej definicji zachowania. Nie ma różnicy w nacisku między tymi trzema; wszystkie opisują "zachowanie, które jest niezdefiniowane".

Teraz oczywiście nie przeszkadza w realizacji od dalszego definiowania zachowania i widzimy, że dla POSIX fputc oznacza ten błąd poprzez EBADF:

[EBADF]

[ CX] [Option Start] Strumień deskryptora pliku nie jest prawidłowym deskryptorem pliku otwartym do zapisu.

Uwaga CX oznacza rozszerzenie standardu C.