- i running error not regularly, can't reproduce it.
- file being read read-only file , can't deleted or modified.
- code not same because part of bigger writing important part of code causing problem.
- 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