如何检查内存地址addr的有效性?规避非法内存写入问题
Great question—this is a common pain point when working with raw memory pointers, especially since IsBadReadPtr is deprecated and fundamentally unreliable (it can introduce race conditions and doesn’t guarantee safety even if it returns "valid"). Plus, catching Access Violation exceptions isn’t an option for you, so let’s break down the only reliable approaches to this problem:
1. Track Memory Ownership Explicitly (The Root Solution)
The best way to avoid invalid pointers is to never let them exist in the first place. If you’re allocating memory yourself (via malloc, new, LocalAlloc, etc.), use RAII (Resource Acquisition Is Initialization) patterns to manage its lifecycle:
- Use smart pointers like
std::unique_ptrorstd::shared_ptrfor dynamic allocations—they automatically invalidate when the memory is freed, so you won’t end up with dangling pointers. - Use standard containers (like
std::vector,std::array) instead of raw arrays—theirdata()method returns a pointer that’s only valid as long as the container isn’t modified or destroyed.
If you’re dealing with pointers from external sources (e.g., APIs), make sure you document and enforce their validity contracts. For example, if a function returns a pointer, confirm under what conditions it’s null or dangling, and handle those cases upfront.
2. Validate Against Known Valid Address Ranges
If you’re working with memory that has a predefined, fixed valid range (e.g., memory-mapped hardware registers, shared memory regions you’ve created), you can check if the pointer falls within that range before writing:
#include <cstdint> // Example: Define your valid memory range (adjust these values to your use case) constexpr uintptr_t MIN_VALID_ADDR = 0x10000; // Avoid low memory (null page, etc.) constexpr uintptr_t MAX_VALID_ADDR = 0x7FFFFFFF; // Example upper bound for user-mode memory bool isPointerValid(const void* addr) { uintptr_t addrValue = reinterpret_cast<uintptr_t>(addr); // Check if the address is within the known valid range return (addrValue >= MIN_VALID_ADDR) && (addrValue <= MAX_VALID_ADDR); }
This only works if you have definitive knowledge of what addresses are safe. It won’t help with arbitrary pointers from unknown sources.
3. Use Structured Exception Handling (SEH) (If You Can)
You mentioned you can’t catch Access Violation exceptions, but it’s worth noting that Windows’ native SEH (__try/__except) is the only way to safely handle invalid memory accesses at runtime—if your environment allows it. For example:
__try { *reinterpret_cast<int*>(addr) = 42; // Your write operation } __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { // Handle the invalid pointer case here }
But again, if SEH is off-limits for your scenario, this isn’t an option.
Critical Note: There’s No "Magic Check" for Arbitrary Pointers
It’s important to be clear: there is no universal function that can guarantee a pointer is valid for writing. Even if you perform a check, there’s a race condition: the memory could be freed or marked invalid right after your check but before your write. This is why IsBadReadPtr is useless—it gives a false sense of security.
The only truly safe approach is to design your code to avoid invalid pointers entirely, using ownership tracking and RAII as described above.
内容的提问来源于stack exchange,提问作者Eugen1344

