0

I'm creating and writing a file with CreateFile2 and WriteFile, then later using readfile with the to read 16 bytes at a time into an __m128i and then performing simd operations on it. Works fine in debug mode, but throws the access denied (0xc0000005) error code in release mode. In my experience, that happens when I'm trying to shove non 16-byte-aligned stuff into 16-byte-aligned stuff. However, I'm unsure where the lack of 16-byte-alignment is first rearing its ugly head.

#define simd __m128i

Is it in the CreateFile2() call?

_CREATEFILE2_EXTENDED_PARAMETERS extend = { 0 };
extend.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
extend.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
extend.dwFileFlags = /*FILE_FLAG_NO_BUFFERING |*/ FILE_FLAG_OVERLAPPED;
extend.dwSecurityQosFlags = SECURITY_ANONYMOUS;
extend.lpSecurityAttributes = nullptr;
extend.hTemplateFile = nullptr;

hMappedFile = CreateFile2(
    testFileName.c_str(),
    GENERIC_READ | GENERIC_WRITE,
    0,
    OPEN_ALWAYS,
    &extend);

...in the WriteFile() call?

_OVERLAPPED positionalData;
positionalData.Offset = 0;
positionalData.OffsetHigh = 0;
positionalData.hEvent = 0;

bool writeCheck = WriteFile(
    hMappedFile,
    &buffer[0],
    vSize,
    NULL,
    &positionalData);

...in the later ReadFile() call?

const simd* FileNodePointer(
    _In_ const uint32_t index) const throw()
{
    std::vector<simd> Node(8);

    _OVERLAPPED positionalData;
    positionalData.Offset = index;
    positionalData.OffsetHigh = 0;
    positionalData.hEvent = 0;

    ReadFile(
        hMappedFile,
        (LPVOID)&Node[0],
        128,
        NULL,
        &positionalData);

    return reinterpret_cast<const simd*>(&Node[0]);
}

How can I enforce 16-byte-alignment here?

Thanks!

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
MNagy
  • 423
  • 7
  • 20
  • What does your debugger tell you? Work backwards from the site of the crash to figure out where the problem originates. – 1201ProgramAlarm Oct 25 '16 at 16:53
  • Get rid of the casts, implicit conversions would be sufficient, reinterpret_cast is dangerous, and the compiler is more likely to be able to spot lifetime errors when the code is simplified. – Ben Voigt Oct 25 '16 at 17:02

1 Answers1

1

TL;DR You have a classic "use after free" error.


None of these functions require 16 byte alignment. If buffering is enabled, they don't care about alignment at all, and if direct I/O is enabled, they require page alignment which is much more restrictive than 16 bytes.

If your data buffer is unaligned, it's because you created it that way. The file I/O is not moving your buffer in memory.

But your access violation is not caused by alignment problems at all, it is the dangling pointer you return from FileNodePointer:

return reinterpret_cast<const simd*>(&Node[0]);

That's a pointer into content of a vector with automatic lifetime, the vector destructor runs during the function return process and frees the memory containing the data you just read from the file.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • A note: your remark is correct and addresses an issue with my code as presented. However, fixing the issue here (i.e. having the function return a vector of __m128i instead of a pointer which ceases to exist after) still has the same access violation. I've changed it to a model which uses FILE_FLAG_NO_BUFFERING as well, (using reads at indices that are multiples of 4096 bytes and of size 4096 bytes at a time), and can confirm in debug mode that the output is correct; but release mode still represents a problem. Any thoughts? – MNagy Oct 26 '16 at 02:15
  • @MNagy yes, i think vector is broken (unable to allocate over-aligned types such as needed by SIMD) and the file access is completely unrelated to your problems. – Ben Voigt Oct 26 '16 at 05:36