Click here to Skip to main content
Click here to Skip to main content

Useful macros for pointer verification

By , 20 Oct 2002
 

Download source file (0.4 Kb)

Introduction

Most know the useful macros provided by various libraries named ASSERT, VERIFY (and similar) which just validates the provided argument. If the validation evaluates to false then a debug notification is raised.

In many cases this is sufficient for simple verifications but validating pointers is not the strength of this methods. Look at this example:

void MyFunction(LPSOMESTRUCT pData)
{
  ASSERT(pData != NULL);
  // ... more code
}
When you pass a NULL pointer to this function it will correctly detect it, but what if you pass 0xcdcdcdcd ? Its not NULL and its most probably not a valid address either. ASSERT will not catch it and you application will throw an exception.

More Macros

Here is a more advanced solution required. One possible solution is the use of the functions provided by the Windows API: IsBadReadPtr(), IsBadWritePtr(), IsBadStringPtr(). These functions take a memory location and a size as arguments and verify that the calling process really has read and/or write access to the location. It might be that the memory at the location is only partially accessible from your process, or that the memory is read or write only. These functions also detect this situations.

I've wrapped this functions into handy macros which you can use similar to the ASSERT and VERIFY macros.

#ifdef _DEBUG

#define VERIFY_ISWRITEPOINTER(a) \
       { if(::IsBadWritePtr(a, sizeof(LPDWORD))) \
		{ ::OutputDebugString(_T("Parameter ") _T(#a) \
		_T(" is not a valid write pointer\r\n"));}}
#define VERIFY_ISREADPOINTER(a) \
		{ if(::IsBadReadPtr(a, sizeof(LPDWORD)))\
		{ ::OutputDebugString(_T("Parameter ") _T(#a) \
		_T(" is not a valid read pointer\r\n"));}}

#define VERIFY_ISWRITEDATA(a, l)\
		{ if(::IsBadWritePtr(a, l)) \
		{ ::OutputDebugString(_T("Parameter ") _T(#a) \
		_T(" is not a valid write area\r\n"));}}
#define VERIFY_ISREADDATA(a, l)\
		{ if(::IsBadReadPtr(a, l))  \
		{ ::OutputDebugString(_T("Parameter ") _T(#a) \
		_T(" is not a valid read area\r\n"));}}

#define ASSERT_ISWRITEPOINTER(a)\
		{ if(::IsBadWritePtr(a, sizeof(LPDWORD))) \
		{ ::OutputDebugString(_T("Parameter ") _T(#a) \
		_T(" is not a valid write pointer\r\n")); ASSERT(false);}}
#define ASSERT_ISREADPOINTER(a)\
		{ if(::IsBadReadPtr(a, sizeof(LPDWORD)))  \
		{ ::OutputDebugString(_T("Parameter ") _T(#a) \
		_T(" is not a valid read pointer\r\n")); ASSERT(false);}}

#define ASSERT_ISWRITEDATA(a, l)\
		{ if(::IsBadWritePtr(a, l)) \
		{ ::OutputDebugString(_T("Parameter ") _T(#a) \
		_T(" is not a valid write area\r\n")); ASSERT(false);}}
#define ASSERT_ISREADDATA(a, l)		{ if(::IsBadReadPtr(a, l))  \
		{ ::OutputDebugString(_T("Parameter ") _T(#a)\
		_T(" is not a valid read area\r\n")); ASSERT(false);}}

#else

#define VERIFY_ISWRITEPOINTER(a)
#define VERIFY_ISREADPOINTER(a)	

#define VERIFY_ISWRITEDATA(a, l)
#define VERIFY_ISREADDATA(a, l)	

#define ASSERT_ISWRITEPOINTER(a)
#define ASSERT_ISREADPOINTER(a)

#define ASSERT_ISWRITEDATA(a, l)
#define ASSERT_ISREADDATA(a, l)

#endif

Our sample from before can be changed to this:

void MyFunction(LPSOMESTRUCT pData)
{
  ASSERT_ISREADDATA(pData, sizeof(SOMESTRUCT));
  // ... more code
}
Now it will correctly assert when you pass the address 0xcdcdcdcd or any other location from which the function can not read at least sizeof(SOMESTRUCT) bytes and the debug output will show "Parameter pData is not a valid read area".

I have found this to be a valuable tool when you write functions which take in or out pointers. Many problems related to bad pointers can easily be cured by using these validation macros.

Compatibility

This is compatible with any Windows version without restriction. It can be used with any Visual C++ version and all eVC versions. Anyway, using the macros is your responsability :)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Andreas Saurwein Franci Gonçalves
CEO Uniwares Ltda.
Brazil Brazil
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralGuaranteed Multithreading Problems Pinmemberpg--az12 Jun '09 - 2:22 
GeneralThese IsBadxxx functions are dangerous! PinmemberAaronJRidout31 Oct '07 - 5:38 
See http://msdn2.microsoft.com/en-us/library/aa366713.aspx and http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx
for explanation, but essentially if you call these functions (via these macros) then you can cause your perfectly valid program to crash later on (i.e. at a time well after you've called the function) because your stack fails to grow when it should, i.e. by calling these functions, the automatic growth of your own stack may fail.
E.g. call one of these functions then allocate a large array on the stack might fail!
 

 
Aaron

GeneralRe: These IsBadxxx functions are dangerous! PinmemberAndreas Saurwein Franci Gonalves31 Oct '07 - 5:56 
GeneralRe: These IsBadxxx functions are dangerous! PinmemberBlake Miller2 May '08 - 5:29 
Generalevc support Pinmemberhillol sarker12 Oct '04 - 22:17 
GeneralRe: evc support PinsussLiby Baby6 Jul '05 - 18:17 
Generalnew -> delete -> valid pointer PinmemberThomas Knauth18 Nov '02 - 5:14 
GeneralRe: new -> delete -> valid pointer PinmemberAndreas Saurwein18 Nov '02 - 5:45 
GeneralRe: new -> delete -> valid pointer PinmemberPhilippe Lhoste2 Dec '02 - 4:56 
GeneralRe: new -> delete -> valid pointer PinmemberAndreas Saurwein2 Dec '02 - 12:04 
Generalsizeof(LPDWORD) PinmemberMartin Bach22 Oct '02 - 1:11 
GeneralRe: sizeof(LPDWORD) PinmemberAndreas Saurwein22 Oct '02 - 2:54 
GeneralRe: sizeof(LPDWORD) PinmemberMartin Bach22 Oct '02 - 4:47 
GeneralRe: sizeof(LPDWORD) PinmemberAndreas Saurwein22 Oct '02 - 6:14 
GeneralRe: sizeof(LPDWORD) PinmemberMartin Bach22 Oct '02 - 20:19 
GeneralRe: sizeof(LPDWORD) PinsussAnonymous24 Oct '02 - 4:26 
GeneralRe: sizeof(LPDWORD) PinmemberAndreas Saurwein24 Oct '02 - 8:43 
GeneralRe: sizeof(LPDWORD) PinsussAnonymous24 Oct '02 - 13:01 
GeneralRe: sizeof(LPDWORD) PinmemberAndreas Saurwein25 Oct '02 - 2:19 
GeneralRe: sizeof(LPDWORD) PinsussAnonymous25 Oct '02 - 5:17 
GeneralRe: sizeof(LPDWORD) PinmemberAndreas Saurwein25 Oct '02 - 5:33 
GeneralRemove MFC dependency... PinmemberNguyen Binh21 Oct '02 - 16:47 
GeneralRe: Remove MFC dependency... PinmemberKarstenK21 Oct '02 - 20:42 
GeneralRe: Remove MFC dependency... PinmemberAndreas Saurwein21 Oct '02 - 22:55 
GeneralRe: Remove MFC dependency... PinmemberNguyen Binh22 Oct '02 - 1:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 21 Oct 2002
Article Copyright 2002 by Andreas Saurwein Franci Gonçalves
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid