是否可以忽略 UnMapViewOFFile() 的错误 487 (ERROR_INVALID_ADDRESS)?
下午好,我们正在尝试构建一个供 Windows 和 Linux 32 位应用程序使用的内存映射文件缓存程序的原型。每次运行原型时,当我们尝试调用 UnMapViewOfFile 取消映射缓存内存映射文件区域时,都会收到错误 487(错误地址无效)。我们认为发生这种情况是因为我们尝试取消映射先前未映射的区域。我们想知道是否可以忽略此错误消息。
我们尽力确保对 MapViewOfFile 的每次调用都与 UnMapViewOfFile 相匹配,如下所示,每次调用 MapViewOfFile 时,我们都使用以下代码:
std::deque<Range> ranges_type;
std::multimap<char *,Range> mmultimap;
MapPtr = (char*)::MapViewOfFile(hMapping,
FILE_MAP_WRITE | FILE_MAP_READ,
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)));
每次取消映射内存映射文件区域时,我们都使用以下摘录
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);
}
: Range 类看起来像这样:
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
感谢您阅读这篇文章。
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,
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
,这是一个错误。您可以通过修复错误来“忽略”该错误。
或者,只需使用 if 测试忽略它即可。 Win32 函数告诉您有一个错误需要修复,但是如果您想忽略它告诉您的内容,当然没有人会阻止您这样做。
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 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:
Or: