简体   繁体   中英

reading a file that doesn't exist

I have got a small program that prints the contents of files using the system call - read.

unsigned char buffer[8];
size_t offset=0;
size_t bytes_read;

int i;

int fd = open(argv[1], O_RDONLY);

do{
    bytes_read = read(fd, buffer, sizeof(buffer));
    printf("0x%06x : ", offset);

    for(i=0; i<bytes_read; ++i)
    {
        printf("%c ", buffer[i]);
    }
    printf("\n");
    offset = offset + bytes_read;
}while(bytes_read == sizeof(buffer));

Now while running I give a file name that doesn't exist. It prints some kind of data mixed with environment variables and a segmentation fault at the end.

How is this possible? What is the program printing?

Thanks, John

It's printing rubbish because fd will invariably be set to -1 which is not a good thing to pass to read since it will, in turn do nothing other than return -1 as well. It will leave your buffer untouched meaning that it's holding whatever rubbish you had in there when you started.

You could probably put the entire do loop inside something like:

if (fd == -1) {
    printf ("error here");
} else {
    // do loop here
}

read is returning -1 because fd is invalid, you store that in bytes_read which is of type size_t which is unsigned, so your loop prints (size_t)-1 chars, which is a very large number, much larger than the size of buffer. So, you're printing a big chunk of your address space and then getting a segfault when you eventually reach the end and access an invalid address.

As others have mentioned (without answering your actual question), you should be checking the results of open for an error. eg,

int fd = open(argv[1], O_RDONLY);
if( fd < 0 ){
    fprintf(stderr, "error opening %s: %s\n", argv[1], strerror(errno));
    exit(1);
}

A caveat: if you do another system call, or call any routine that might do a system call (eg, printf) before calling strerror, you must save errno and then pass the saved copy to strerror.

Another note about your program:

while(bytes_read == sizeof(buffer))

This is not a good test, because read can return less than the amount you ask for. Your loop should continue until read returns <= 0.

You should probably check that the file descriptor returned by open is valid before using it. As per these docs , you should get a non-negative response for a valid file. Reading from an invalid descriptor is likely the source of your problem.

Upon successful completion, open function shall open the file and return a non-negative integer representing the file descriptor. Otherwise, -1 shall be returned and errno set to indicate the error. So please check fd before entering the loop to perform the read.

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