lundi 3 août 2015

std::ofstream fails to open large files with std::ios::ate on win7/64 and msvc2013

On windows7 x64, I'm trying to modify an existing binary file, which is located in the root dir of C:, which is an NTFS filesystem.

The following code is compiled with MSVC Community 2013 (12.0.31101.00 Update 4):

#include <QFileInfo>
#include <fstream>  //std::ifstream
#include <iostream> // std::cout
#include <windows.h>

int main(int argc, char *argv[])
{
const QDir dir("c:\\");
const QStringList fileNames = dir.entryList(QStringList({ "*.tst" }), QDir::Files, QDir::Size | QDir::Reversed);

std::ios::openmode m = std::ios::out | std::ios::in | std::ios::binary | std::ios::ate;

for (int i = 0; i < fileNames.size(); i++)
{
    const QString filename = dir.absoluteFilePath(fileNames.at(i));
    const QFileInfo fileinfo(filename);
    std::ofstream ofs(filename.toLatin1().constData(), m);
    qDebug()
        << "ofstream on" << filename
        << "size" << fileinfo.size()
        << "\n\tis_open:" << ofs.is_open()
        << "\n\tgood:" << ofs.good()
        << "\n\tbad:" << ofs.bad()
        << "\n\teof:" << ofs.eof()
        << "\n\tfail:" << ofs.fail()
        << "\n\terror:" << strerror(errno)
        << "\n\tlastError:" << QString::fromStdString(GetLastErrorAsString());
}

// and now again, but without std::ios::ate
m = std::ios::out | std::ios::in | std::ios::binary;

for (int i = 0; i < fileNames.size(); i++)
{
    const QString filename = dir.absoluteFilePath(fileNames.at(i));
    const QFileInfo fileinfo(filename);
    std::ofstream ofs(filename.toLatin1().constData(), m);
    qDebug()
        << "ofstream on" << filename
        << "size" << fileinfo.size()
        << "\n\tis_open:" << ofs.is_open()
        << "\n\tgood:" << ofs.good()
        << "\n\tbad:" << ofs.bad()
        << "\n\teof:" << ofs.eof()
        << "\n\tfail:" << ofs.fail()
        << "\n\terror:" << strerror(errno)
        << "\n\tlastError:" << QString::fromStdString(GetLastErrorAsString());
}
}

The output is:

ofstream on "c:/4294967294.tst" size 4294967294
    is_open: true
    good: true
    bad: false
    eof: false
    fail: false
    error: No error
    lastError: ""
ofstream on "c:/4294967295.tst" size 4294967295
    is_open: false
    good: false
    bad: false
    eof: false
    fail: true
    error: No error
    lastError: ""

ofstream on "c:/4294967294.tst" size 4294967294
    is_open: true
    good: true
    bad: false
    eof: false
    fail: false
    error: No error
    lastError: ""
ofstream on "c:/4294967295.tst" size 4294967295
    is_open: true
    good: true
    bad: false
    eof: false
    fail: false
    error: No error
    lastError: ""

So it seems I cannot open files >= (2^32)-1 bytes using the std::ios::ate flag. I can't quite believe this happens on a 64bit windows with NTFS filesystem. I tried to run this code as administrator... it makes no difference.

  • Why does this happen?
  • What can I do? (no, I don't want to use boost)
  • Does this still happen with msvc 2015?

Thank you!

Aucun commentaire:

Enregistrer un commentaire