c++ - cpp file reading error with stat and read() -


  1. i running error not regularly, can't reproduce it.
  2. file being read read-only file , can't deleted or modified.
  3. code not same because part of bigger writing important part of code causing problem.
  4. this code explaining purposes , not reproduce problem because of point 1

i trying read file using

#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <memory> #include <exception> #include <iostream> #include <glog/logging.h> using namespace std; int main() {     string filename="blah";     struct stat filestat;     int status = ::stat(filename.c_str(), &filestat);     if (status != 0) {      log(error) << "error stating file";     }     size_t filesize = filestat.st_size;     // filesize 79626240. trying read block starting      // 67108864 bytes, there 1251736     size_t fileblocksize = 16 * 1024 * 1024;     size_t numblocks = filesize / fileblocksize;         size_t offset = numblocks;     size_t actualsize = filesize - offset * fileblocksize;     if (actualsize == 0) {       log(info) << "you read entire file";       return 1;     }      int fd = ::open(filename.c_str(), o_rdonly);     if (fd < 0) {       throw std::runtime_error("error opening file");     } else if (offset > 0 && lseek(fd, offset, seek_set) < 0) {      throw std::runtime_error("error seeking file");     }      uint64_t readblocksize = 256 * 1024;         char *data = new char[readblocksize + 1];     uint64_t totalread = 0;     while (totalread < actualsize) {       ssize_t numread = ::read(fd, data, readblocksize);       // use data read upto numread       if (numread == 0) {        log(error) << "reached end of file";        break;       } else if (numread < 0) {        throw std::runtime_error("read unsuccessful");       }        totalread += numread;     }     if (totalread != actualsize) {        log(error) << "error reading file";     } } 

if imagine me slicing file blocks of size 16 mybtes , reading last block. reading block in loop smaller size, eof before can finish reading entire block. can ever happen size reported stat greater size of data in file ?

the output see :

reached end of file error reading file 

i don't need alternative solutions, can other things such lseek end wanna know why happening ?

ps not because of number of blocks on disk. using st_size , nothing more

you must take care using stat on file, better use fstat avoid toctou race conditions.

int filedescriptor = -1; struct stat filestat; std::vector<char> filecontent; std::string filename("test.txt");  filedescriptor = open(filename.c_str(),o_rdonly); // error check of filedescriptor fstat(filedescriptor,&filestat); // error check of fstat filecontent.resize(filestat.st_size); ::read(filedescriptor,filecontent.data(),filestat.st_size);  close(filedescriptor); 

additionally, consider read may return value lesser filestat.st_size , must read remaining bytes(pretty hard in file i/o, quite common sockets though), code small example.

edit

i have copied code , modified load local 9mb file, after compilation g++ -g -std=c++11 -lglog main.cpp, have setup breakpoint in line 51

if (totalread != actualsize)

this result debug session:

(gdb) b main.cpp:51 breakpoint 1 @ 0x4013fc: file main.cpp, line 51.

(gdb) r starting program: /home/jpalma/documents/functiontest/a.out

[thread debugging using libthread_db enabled] using host libthread_db library "/lib64/libthread_db.so.1".

breakpoint 1, main () @ main.cpp:51

51 if (totalread !=> actualsize) {

(gdb) p totalread

$1 = 9000032

(gdb) p actualsize

$2 = 9000032

so program works flawless me. maybe have problem in filesystem or not related this.

i'm using ext4 filesystem.

ll reports size file i'm reading 9000032 abr 29 16:10 webdev.pdf, can see correct. page size

$ getconf pagesize 4096