我有一些Visual C++代码接收指向缓冲区的指针,该缓冲区包含需要由我的代码处理的数据和该缓冲区的长度.由于我的控制之外的错误,有时这个指针未初始化我的代码或者不适合阅读(即当我尝试访问缓冲区中的数据时它会导致崩溃.)
所以,我需要在使用它之前验证这个指针.我不想使用IsBadReadPtr或IsBadWritePtr,因为每个人都认为他们是错误的.(谷歌他们的例子.)他们也不是线程安全的 - 在这种情况下可能不是一个问题,虽然线程安全的解决方案会很好.
我已经看到了通过使用VirtualQuery实现这一点的建议,或者只是在异常处理程序中执行memcpy.但是,需要进行此检查的代码是时间敏感的,因此我需要最有效的检查,这也是100%有效.任何想法,将不胜感激.
为了清楚起见:我知道最好的做法是只读坏指针,让它引起异常,然后追溯到源并修复实际问题.但是,在这种情况下,坏指针来自我无法控制的Microsoft代码,所以我必须验证它们.
另请注意,我不关心指向的数据是否有效.我的代码正在寻找特定的数据模式,如果没有找到它们将忽略它们.我只是想防止在对这些数据运行memcpy时发生崩溃,并且在尝试memcpy时处理异常需要在我的代码中更改十几个地方(但如果我有像IsBadReadPtr这样的东西来调用我只会必须在一个地方更改代码).
bool IsBadReadPtr(void* p) { MEMORY_BASIC_INFORMATION mbi = {0}; if (::VirtualQuery(p, &mbi, sizeof(mbi))) { DWORD mask = (PAGE_READONLY|PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY); bool b = !(mbi.Protect & mask); // check the page is not a guard page if (mbi.Protect & (PAGE_GUARD|PAGE_NOACCESS)) b = true; return b; } return true; }
一个线程安全的解决方案会很好
我猜它只是IsBadWritePtr不是线程安全的.
只是在异常处理程序中执行memcpy
这实际上是IsBadReadPtr正在做的...如果你在你的代码中做了,那么你的代码将与IsBadReadPtr实现具有相同的错误:http://blogs.msdn.com/oldnewthing/archive/2006/09/ 27/773741.aspx
- 编辑: -
我读过的IsBadReadPtr唯一的问题是坏指针可能指向(因此你可能不小心碰到)堆栈的防护页面.也许你可以通过以下方式避免这个问题(因此安全地使用IsBadReadPtr):
了解您的流程中正在运行的线程
知道线程堆栈的位置,以及它们的大小
走开每个堆栈,在开始调用isBadReadPtr之前,至少触摸一次堆栈的每个页面
此外,与上述URL相关的一些注释也建议使用VirtualQuery.
这些功能使用不好的原因是问题无法可靠地解决.
如果您正在调用的函数返回指向已分配的内存的指针,那么它看起来有效,但是它指向其他不相关的数据,并且如果您使用它将损坏您的应用程序.
最有可能的是,您调用的函数实际上表现正常,并且您正在滥用它.(不保证,但通常就是这种情况.)
它的功能是什么?