views:

54

answers:

2

Hi,

due to performance reasons I didn't feel like using fstream for just one time. Seems like a very bad idea to use WinAPI functions with a std::string instead of a plain char array. All in all I would like you to tell me why the following snippet just won't work (empty stBuffer stays empty) and what I'd need to do to get it fixed.

Thanks in advance!

std::size_t Get(const std::string &stFileName, std::string &stBuffer)
{
    HANDLE    hFile        = ::CreateFileA(stFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD    dwBytesRead    = 0;

    if(hFile != INVALID_HANDLE_VALUE)
    {
        DWORD    dwFileSize    = ::GetFileSize(hFile, NULL);

        stBuffer.reserve(dwFileSize + 1);
        ::ReadFile(hFile, &stBuffer[0], dwFileSize, &dwBytesRead, NULL);
        stBuffer[dwFileSize] = '\0';
        ::CloseHandle(hFile);
    }

    return dwBytesRead;
}
+1  A: 

Consider difference between reserve() and resize() members. So the solution would be:

stBuffer.resize(dwFileSize + 1);
baton
Uhm, then it should be `.resize(dwFileSize)` - the `+1` is superficial.
Dummy00001
@Dummy00001 - the code is written to explicitly null-terminate the file contents. Unless this is wrong then the +1 is needed.
Steve Townsend
@Steve: Oops. You are *right*. The `'\0'` termination is also wrong in the original code: `std::string` doesn't need that.
Dummy00001
With respect, it's not for you to decide whether that's wrong or not. As noted elsewhere std::string can contain embedded null characters.
Steve Townsend
Thanks! That helped!
Oliver Baur
+2  A: 

Because a std::string can contain embedded '\0' characters, it has to keep track of its own length in a separate way.
Your problem is that std::string::reserve() does not change the length of the string. It just pre-allocates some memory for the string to grow into. The solution is to use std::string::resize() and let the WinAPI function overwrite the string contents.

As a side-note: Currently, it is not guaranteed that std::string uses a contiguous buffer, but to my knowledge, all current implementations do use a contiguous buffer and it will be a requirement in the next standard.

Bart van Ingen Schenau
Thanks **a lot** for explaining!
Oliver Baur