0
votes

I`m struggling for the past many hours with the following problem: I try to read a file using CreateFile and ReadFile methods.

Here is the code:

char* Utils::ReadFromFile(wchar_t* path) {

HANDLE hFile = CreateFile(
    path,                                                   // long pointer word string file path (16 bit UNICODE char pointer)
    GENERIC_READ,                                           // access to file
    0,                                                      // share mode ( 0 - prevents others from opening/readin/etc)
    NULL,                                                   // security attributes
    OPEN_EXISTING,                                          // action to take on file -- returns ERROR_FILE_NOT_FOUND 
    FILE_ATTRIBUTE_READONLY,                                // readonly and offset possibility
    NULL                                                    // when opening an existing file, this parameter is ignored
    );

if (hFile == INVALID_HANDLE_VALUE) {
    std::cout << "File opening failed" << endl;
    std::cout << "Details: \n" << Utils::GetLastErrorMessage() << endl;
    CloseHandle(hFile);
    hFile = NULL;
    return nullptr;
}

LARGE_INTEGER largeInteger;
GetFileSizeEx(hFile, &largeInteger);

LONGLONG  fileSize = largeInteger.QuadPart;

if (fileSize == 0) {
    std::cout << "Error when reading file size" << endl;
    std::cout << "Details: \n" << Utils::GetLastErrorMessage() << endl;
    CloseHandle(hFile);
    hFile = NULL;
    return nullptr;
}

cout << "File size: " << fileSize << endl;

char* bytesRead;
bytesRead = new char(fileSize);

int currentOffset = 0;
int attempts = 0;
int nBytesToBeRead = BYTES_TO_READ;
//DWORD nBytesRead = 0;
OVERLAPPED overlap{};
errno_t status;

while (currentOffset < fileSize) {

    overlap.Offset = currentOffset;

    if (fileSize - currentOffset < nBytesToBeRead)
        nBytesToBeRead = fileSize - currentOffset;

    status = ReadFile(
        hFile,                              // file handler
        bytesRead + currentOffset,          // byted read from file
        nBytesToBeRead,                     // number of bytes to read
        NULL,                               // number of bytes read
        &overlap                            // overlap parameter
        );

    if (status == 0) {
        std::cout << "Error when reading file at offset: " << currentOffset << endl;
        std::cout << "Details: \n" << Utils::GetLastErrorMessage() << endl;

        attempts++;
        std::cout << "Attempt: " << attempts << endl;

        if (attempts == 3) {
            cout << "The operation could not be performed. Closing..." << endl;
            CloseHandle(hFile);
            hFile = NULL;
            return nullptr;
        }
        continue;
    }
    else {
        cout << "Read from offset: " << currentOffset;// << " -- " << overlap.InternalHigh << endl;

        currentOffset += nBytesToBeRead;

        if (currentOffset == fileSize) {
            cout << "File reading completed" << endl;
            break;
        }
    }
}

CloseHandle(hFile);

return bytesRead;
}

When running this method I get some weird results:

  1. One time it worked perfectly
  2. Very often I get Access violation reading location for currentOffset variable and overlap.InternalHigh ( I commented last one), with last method from CallStack being

    msvcp140d.dll!std::locale::locale(const std::locale & _Right) Line 326 C++

  3. Sometimes the function runs perfectly, but I get access violation reading location when trying to exit main function with last method from CallStack being

    ucrtbased.dll!_CrtIsValidHeapPointer(const void * block) Line 1385 C++

I read the windows documentation thoroughly regarding the methods I use and checked the Internet for any solution I could find, but without any result. I don't understand this behaviour, getting different errors when running cod multiple times, and therefore I can`t get to a solution for this problem.

Note: The reason I am reading the file in repeated calls is not relevant. I tried reading with a single call and the result is the same.

Thank you in advance

1
Change bytesRead = new char(fileSize); to bytesRead = new char[fileSize];Richard Critten
I don't know what is new char(fileSize); supposed to do. I had no idea it would even compile.Mike Nakis
Indeed, that was the problem. How did I just miss that...Thank youAlinF

1 Answers

0
votes

You are allocating a single char for bytesRead, not an array of fileSize chars:

char* bytesRead;
bytesRead = new char(fileSize); // allocate a char and initialize it with fileSize value
bytesRead = new char[fileSize]; // allocate an array of fileSize chars