简体   繁体   中英

Why does the calling of dup2 go wrong?

As you see, the program has two file pointer sport and fruit point to the file fruit.txt. The problem is that after run the program, sport.txt is empty and fruit.txt contains Chinese characters. I expected that the sport.txt should contains the word "basketball" because it is written to the file before redirecting happens. So, what is wrong here?

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "../cus_header/cus_header.h"

int main(){

    FILE *fruit = fopen("fruit.txt", "w");
    if(!fruit)
        error("cannot open fruit.txt");

    FILE *sport = fopen("sport.txt", "w");
    if(!sport)
        error("cannot open sport.txt");

    int de_sport = fileno(sport);
    int de_fruit = fileno(fruit);

    printf("file number of sport.txt: %i and of fruit.txt: %i\n", de_sport, de_fruit);

    fwrite("basketball", sizeof(char), 10, sport);

    fwrite("apple", sizeof(char), 6, fruit);

    if(dup2(de_fruit, de_sport) == -1)
        error("cannot redirect");

    fwrite("basketball", sizeof(char), 10, sport); //???
    fwrite("apple", sizeof(char), 6, fruit); // ???

    fclose(sport);
    fclose(fruit);

    return 0;
}

As the comments already mention, you shouldn't mix file manipulation with streams (using FILE* , fopen , fwrite , fclose ) with raw file manipulation (using file descriptors, open , write , close , dup2 ). And especially don't mix them on the same file pointer/descriptor like you are doing in this piece of code.

Let's go through the code to see why it behaves the way it does:

FILE *fruit = fopen("fruit.txt", "w");
...
FILE *sport = fopen("sport.txt", "w");

You shouldn't care about how the FILE structure looks like, let's just suppose it keeps the underlying file descriptor somewhere.

int de_sport = fileno(sport);
int de_fruit = fileno(fruit);

You create local variables holding the same file descriptors as the two FILE* refer.

fwrite("basketball", sizeof(char), 10, sport);
fwrite("apple", sizeof(char), 6, fruit);

You write something in each of the two files. Because C file streams are buffered by default, the actual writing in the file on disk might not happen right away (and in your case it doesn't).

dup2(de_fruit, de_sport)

This closes the file descriptor de_sport and makes it refer to the same file as de_fruit . The actual numerical values remain the same, only the actual files that they refer to are changed. This means that the two FILE handles will write to the same file after the dup2 call.

fwrite("basketball", sizeof(char), 10, sport); //???
fwrite("apple", sizeof(char), 6, fruit); // ???

This will write to the same underlying file because the two descriptors now refer to the same file. But again, because streams are buffered, this might actually just append to the buffers of those two FILE* s.

fclose(sport);
fclose(fruit);

This flushes the buffers, so the actual writing to disk happens here. Because the descriptors have been changed, if no flushing happened until now, both streams will actually flush to the same file on disk.

This is probably why you're seeing that behavior, but keep in mind that what you're doing is not safe and that the behavior or file contents might differ.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM