0

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;
}
2
  • I don't see a problem with using std::strings with winAPI. I'm doing it in my project. Commented Sep 9, 2010 at 9:27
  • 2
    While with VCs (and i think all major compilers) standard libraries std::string has a contigous buffer, this is not guaranteed by C++03. C++0x will guarantee that and until then std::vector<char> would be the "clean" solution. Commented Sep 9, 2010 at 9:32

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for explaining!
1

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

stBuffer.resize(dwFileSize + 1);

4 Comments

Uhm, then it should be .resize(dwFileSize) - the +1 is superficial.
@Dummy00001 - the code is written to explicitly null-terminate the file contents. Unless this is wrong then the +1 is needed.
@Steve: Oops. You are right. The '\0' termination is also wrong in the original code: std::string doesn't need that.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.