|
Boost Users : |
From: Allen Cronce (allenslists_at_[hidden])
Date: 2008-08-28 23:31:05
Hi all,
I'm trying to use mapped_file from the Boost 1.35.0 Iostreams library
to open a data file for reading and writing. My code works fine under
Mac OS X, which is posix, of course. But under Windows (built with
VS2005), I get an access error.
Here's a code sample that works on Mac OS X and fails under Windows:
--snip--
/**
Test boost iostream mapped_file.
*/
static int BoostMappedFileTest(void)
{
int result = 0;
std::cout << "\nRunning BoostMappedFileTest..." << std::endl;
// Initialize our test directory
fs::path testDirPath( "BoostMappedFileTest" );
create_directory(testDirPath);
// Initialize a test file buffer with some data
const size_t kTestFileSize = 4096;
boost::scoped_array<char> fileBuffer( new char[kTestFileSize] );
char* pCur = fileBuffer.get();
char curChar = 0;
for( size_t i = 0; i < kTestFileSize; ++i )
{
*pCur++ = curChar++;
}
// Write the data to a test file. Be sure to explicitly close it.
fs::path testFilePath( testDirPath / "test_mapped_file" );
boost::filesystem::ofstream testFile( testFilePath, ios::trunc |
ios::binary );
testFile.write(fileBuffer.get(), kTestFileSize);
testFile.close();
// Try and open the test file as a memory mapped file.
string testFilePathStr = testFilePath.file_string();
mapped_file mappedFile(testFilePathStr);
// We never get here under Windows with boost 1.35.0. The file fails to
// open with an access error, although it throws with a more obscure
error
// due to a clean up bug.
// Compare the mapped file data to our original buffer
const char* mmConstData = mappedFile.const_data();
bool compareSucceeded = (0 == memcmp(fileBuffer.get(), mmConstData,
kTestFileSize));
if (!compareSucceeded)
{
throw runtime_error("The boost memory mapped file data doesn't match
our buffer!");
}
return result;
}
--snip--
The problem seems to come from passing GENERIC_ALL as the
"dwDesiredAccess" parameter to the CreateFileA call. If I change the
implementation to pass GENERIC_READ | GENERIC_WRITE, then it works in
my test scenario. Please note that I haven't tried pointing the
current code at an actual executable to see if it works with
GENERIC_ALL.
If you assume a strict interpretation of the mapped_file API, the mode
of BOOST_IOS::in would map to GENERIC_READ in the Windows world, and
BOOST_IOS::out would map to GENERIC_WRITE. There is no corresponding
"execute" flag that I can see in this API.
Since I'm only interested in mapping data files, I could certainly
modify the boost 1.35.0 sources so that only GENERIC_READ and
GENERIC_WRITE are passed to the Windows API depending on what
BOOST_IOS mode was specified. But I'm not sure of what dependancies
may exist between the mapped_file implementation and other boost
libraries. The interprocess library, for example, hasn't yet fallen
under my sphere of research ;-)
Could someone please advise me as to the best course of action that
will allow me to open memory mapped data files on Windows without
adversely impacting the rest of the boost libraries?
BTW, there's a secondary problem where if an error happens at
CreateFileA, the clean up code fails and throws an invalid handle
exception. This is because the mapped_handle_ member variable is
initialized to NULL instead of INVALID_HANDLE_VALUE (which is what the
clean up test is looking for).
After code inspection of the svn trunk, I *think* this secondary issue
has already been resolved. However, the latest sources look like
they're still using GENERIC_ALL as the access parameter to the
CreateFile, so my reported problem is still relevant and needs to be
resolved.
Thanks in advance for any suggestions.
Best,
-- Allen Cronce
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net