|Date:||September 27, 2006 / year-entry #330|
|Summary:||Often I'll see code that tries to "protect" against invalid pointer parameters. This is usually done by calling a function like IsBadWritePtr. But this is a bad idea. IsBadWritePtr should really be called CrashProgramRandomly. The documentation for the IsBadXxxPtr functions presents the technical reasons why, but I'm going to dig a little deeper. For one...|
Often I'll see code that tries to "protect" against invalid pointer parameters. This is usually done by calling a function like
The documentation for the
Alternatively, it's possible that your function was called by some code that intentionally passed a pointer to a guard page (or a
"Yeah, but my code doesn't use guard pages or play games with
And second, your program does use guard pages; you just don't realize it. The dynamic growth of the stack is performed via guard pages: Just past the last valid page on the stack is a guard page. When the stack grows into the guard page, a guard page exception is raised, which the default exception handler handles by committing a new stack page and setting the next page to be a guard page.
(I suspect this design was chosen in order to avoid having to commit the entire memory necessary for all thread stacks. Since the default thread stack size is a megabyte, this would have meant that a program with ten threads would commit ten megabytes of memory, even though each thread probably uses only 24KB of that commitment. When you have a small pagefile or are running without a pagefile entirely, you don't want to waste 97% of your commit limit on unused stack memory.)
"But what should I do, then, if somebody passes me a bad pointer?"
You should crash.
In the Win32 programming model, exceptions are truly exceptional. As a general rule, you shouldn't try to catch them. And even if you decide you want to catch them, you need to be very careful that you catch exactly what you want and no more.
Trying to intercept the invalid pointer and returning an error code creates nondeterministic behavior. Where do invalid pointers come from? Typically they are caused by programming errors. Using memory after freeing it, using uninitialized memory, that sort of thing. Consequently, an invalid pointer might actually point to valid memory, if for example the heap page that used to contain the memory has not been decomitted, or if the uninitialized memory contains a value that when reinterpreted as a pointer just happens to be a pointer to memory that is valid right now. On the other hand, it might point to truly invalid memory. If you use
In other words
Many teams at Microsoft have rediscovered that
There is a subtlety to this advice that you should just crash when given invalid input, which I'll take up next time.
<-- Back to Old New Thing Archive Index