2016-04-23 22 views
0

Ich habe dieses C-Code:Lesen Berichte Bad File Descriptor trotz getc erfolgreich die gleiche fd mit einem Zeichen lesen

FILE * fd = fopen(filename,"rb"); 
printf("%c ",(char)getc(fd)); // returns expected char 
unsigned char buffer[10]; 
printf("%d ",read(fd, &buffer, 10)); // -1 
printf("%d\n",errno); // 9 

getc ein Zeichen aus der Eingabedatei zurückgibt, wie erwartet. read gibt jedoch einen Fehler (-1) zurück und errno wird auf 9 (beschädigter Dateideskriptor) gesetzt. Offensichtlich ist der Dateideskriptor OK, da getc es schafft, ein Zeichen zu lesen.

Was ist das Problem hier?

+3

Ruft der Compiler nicht eine Warnung an Sie? Warnungen ernst nehmen! – alk

Antwort

2

fopen und read sind Funktionen verschiedener Familien. Die Familien sind:

  • fopen mit fread (und auch getc) aus der C-Standardbibliothek.

  • open mit read, aus der POSIX-Spezifikation.

Die erste Familie verwendet Dateizeiger als FILE* Typen, während die zweite Datei-Deskriptoren als int Typen verwendet. Sie können die beiden Familien nicht mischen, solange Sie nicht von einem Dateideskriptortyp in den anderen konvertieren. Die Konvertierung von FILE* zu int erfolgt mit der POSIX-Funktion fileno.

In Ihrem Fall verwenden Sie fread, um aus der Datei zu lesen.

+0

notice '& fd' in' read (fd, & buffer, 10) ' – shrike

0

Es ist komischer Code. Sie möchten den Rückgabecode von read ausgeben, nicht die gelesenen Daten?

zuerst Ihre Lese beheben, müssen Sie fread statt lesen:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *" stream); 

Der Absturz verursacht wird, weil Sie die Adresse Puffer überschreiben, Sie schreiben nicht in den Puffer selbst.

So sollte printf("%d ",read(fd, &buffer, 10));printf("%d ",fread(buffer, 1, 10, fd)); stattdessen sein, 10 (nmemb=10) Bytes (size=1) in den Puffer zu lesen.

+0

a FILE *, zurückgegeben von fopen() ist kein Dateideskriptor; read() benötigt einen Dateideskriptor; fread() sollte stattdessen hier verwendet werden. - shrike gerade jetzt bearbeiten – shrike

+0

@shrike danke, konzentrierte ich mich stattdessen auf den falschen Zeiger. –

1

Statt read(fd, &buffer, 10)
Sie verwenden möchten: fread(buffer, 1, 10, fd)

ein FILE* ist keine Datei-Beschreiber, es ist ein Strom; Deshalb müssen Sie fread() (das einen Stream benötigt) anstelle von read() (die einen Dateideskriptor benötigt) verwenden. Außerdem sollte buffer anstelle von &buffer verwendet werden (was zu UB führen würde).