Reputation: 1414
Good morning, I am trying to write a cMemoryMappedFile class that deals with large files that cannot be mapped to one view in Win32. The code is at the pastebin url.
In GetPointer(), we are trying to carefully map and unmap file regions as they are needed. We are encountering an access violation in GetPointer() on the line marked with the comment // crashes here if adjusted ptr is bad ptr.
The test program is:
int TotalKeys = 2709783;
try {
mmapFile = new cMemoryMappedFile(TotalKeys * 54 + 1);
}
catch (cException e) {
printf("catch cMemoryMappedFile\n");
throwl
}
for (i = 0; i < 50000; i++) {
mmapFile->GetPointer(i * 54);
}
When i equals 28521 and i * 54 = 1540134, we get an access violation reading location 0x0024000. The MEM_BLOCK_SIZE is on the 64K alignment required by MapViewOfFile, MEM_BLOCK_SIZE = 65536 * 2. We are running Windows XP Professional Version 2002 Service Pack 3, 32 bit version. What is puzzling is that we are trying the move the map view within the file mapping. Please suggest the cause of the access violation if you wish.
Thank you.
Upvotes: 0
Views: 450
Reputation: 1414
I fixed the access violation and the Microsoft operator delete error. The modified code is in the www.pastebin.com url.<iframe src="http://pastebin.com/embed_iframe.php?i=4dsVfkzg" style="border:none;width:100%"></iframe> > I wish to thank Adrian
McCarthy and Andre Caron for their help.
Upvotes: 0
Reputation: 48038
This calculation seems overly complicated.
char * cMemoryMappedFile::GetPointer(int n){
unsigned int baseoff;
if( n < MEM_BLOCK_SIZE / 2)
{
baseoff = 0;
}
else
{
baseoff = ((n + MEM_BLOCK_SIZE / 4) &
(~(MEM_BLOCK_SIZE / 2 - 1))) - MEM_BLOCK_SIZE / 2;
}
...
As I understand, n
is the desired offset into the file, and baseoff
is the first address we'll actually map. We want the largest baseoff
<= n
, where baseoff
is a multiple of MEM_BLOCK_SIZE
. So how about:
unsigned int baseoff = (n / MEM_BLOCK_SIZE) * MEM_BLOCK_SIZE;
Later:
MapPtr = (char*)::MapViewOfFile(hMapping, FILE_MAP_WRITE | FILE_MAP_READ, 0,
baseoff, mappedlength);
You should check the result of MapViewOfFile
.
It's not clear what you want the return value to be. I'm assuming adjustedptr + n
should point to the originally requested byte. But then you try to access *adjustedptr
, which is not guaranteed to be part of the view when the base offset is larger than MEM_BLOCK_SIZE
. I think you want the printf to use *(adjustedptr + n)
or adjustedptr[n]
. Or maybe you're trying to access the first byte actually mapped, which would be adjustedptr[baseoff]
.
Upvotes: 2