开发者

Is it possible to ignore an Error 487 (ERROR_INVALID_ADDRESS) for UnMapViewOFFile()?

Good afternoon, We are trying to build a prototype of Memory Mapped File Caching program for use by Windows and Linux 32 bit applications. Every time we run the prototype we get an Error 487(Error Invalid Address) when we try call UnMapViewOfFile to unmap a a cached memory mapped file region. We think this is happening because we trying a unmap a previouslu unmapped region. We were wondering if it is possible to ignore this error message.

We try our best to make sure that every call to MapViewOfFile is matched by an UnMapViewOfFile in the following way, Every time we call MapViewOfFile , we use the following code:

std::deque<Range> ranges_type;

std::multimap<char *,Range> mmultimap;

MapPtr = (char*)::MapViewOfFile(hMapping,
                                FILE_MAP_WRITE | FILE_MAP_READ,
                            开发者_JS百科    0, baseoff,
                                mappedlength);
if (MapPtr == 0){
    DWORD lasterr = GetLastError();
    ErrorMessage(lasterr);
}

ranges_type.insert(RangeDeque::value_type(
                       PreviousNCopy,
                       PreviousN,
                       adjustedptr + n,
                       MapPtr,
                       TimeStamp,
                       mappedlength));

mmultimap.insert(RangeMultiMap::value_type(
                     MapPtr,
                     Range(PreviousNCopy,
                           PreviousN,
                           adjustedptr + n,
                           MapPtr,
                           TimeStamp,
                           mappedlength)));

Everytime we unmap a memory mapped file region, we use the following excerpt:

typedef std::multimap<char *,Range>::const_iterator I;
numerased = 0;
std::pair<I,I> b = mmultimap.equal_range(TmpPrevMapPtr);
for (I i=b.first; i != b.second; ++i){ 
    std::dequeue<Range>::iterator iter;
    iter = std::lower_bound(ranges_type.begin(),
                            ranges_type.end(),
                            i->second);
    if (iter != ranges_type.end() && !(i->second < *iter)){
        ranges_type.erase(iter);
        numerased++;
    }
}

erasecount = mmultimap.erase(TmpPrevMapPtr);
retval = UnmapViewOfFile(TmpPrevMapPtr);
if (retval == 0){
    DWORD lasterr = GetLastError();
    ErrorMessage(lasterr);
}

The class Range looks like this:

class Range {
public:
    explicit Range(int item){
        mLow = item;
        mHigh = item;
        mPtr  = 0;
        mMapPtr = 0;
        mStamp = 0;
        mMappedLength = 0;
    }
    Range(int low, int high, char* ptr = 0,char* mapptr = 0, int stamp = 0, int currMappedLength = 0){
        mLow = low;
        mHigh = high;
        mPtr  = ptr;
        mMapPtr = mapptr;
        mStamp = stamp;
        mMappedLength = currMappedLength;
    }

    Range(const Range& r):

    bool operator==(const Range& rhs) const{
        return (mLow <= rhs.mLow && mHigh >= rhs.mHigh);
    }
    bool operator<(const Range& rhs) const{
        return mHigh < rhs.mHigh;      
    } 

public:
    int mLow;   
    int mHigh; 
    char* mPtr;
    char* mMapPtr;
    int mStamp;
    int mMappedLength;
}; // class Range 

Thank you for reading this post.


we trying a unmap a previouslu unmapped region

That is a bug, period. You "ignore" the error by fixing the bug.

Alternately, just ignore it with an if test. The Win32 function is telling you there's a bug to fix, but if you want to ignore what it's telling you of course nobody is going to prevent you from doing so.


You need to fix the underlying bug that causes the memory region to be unmapped twice. After all consider this:

  • You map a region of memory (call it A) at address 0x42000000
  • You unmap A at 0x42000000
  • You map a region of memory B at the same address 0x42000000
  • You double-unmap A at 0x42000000 - only this time B is unmapped
  • You try to access B, and crash.

You need to figure out where you're double-unmapping this memory and fix it, or something like this can happen eventually. If you hide the error, it'll just make this that much more confusing to debug.

Now, your accounting is fine for debug purposes, but it's not fixing the root cause; you're not keeping good track of your memory mappings in the first place. It's not possible to comment much more on the small portion of code you've posted, but you should be looking at the code that decides when to map/unmap as what you need to fix; don't just try to suppress the double-frees when it's too late. After all, if you're double-freeing this memory mapping, does this mean your code thinks it's still mapped? In which case what's stopping access-after-free problems from occurring:

  • Map A at 0x42000000
  • Unmap A at 0x42000000
  • Access A (crash!)
  • Try to double-unmap A at 0x42000000 (not reached, due to the crash)

Or:

  • You map a region of memory (call it A) at address 0x42000000
  • You unmap A at 0x42000000
  • You map a region of memory B at the same address 0x42000000
  • Thinking A is still mapped, you access memory at 0x42000000 and access B instead. Confusion! Or possibly data corruption!
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜