Click here to Skip to main content
15,860,859 members
Articles / Mobile Apps

Useful Macros for Pointer Verification

Rate me:
Please Sign up or sign in to vote.
4.33/5 (5 votes)
20 Oct 20022 min read 164.9K   517   45   42
A few macros to validate pointers passed to functions

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 method. Look at this example:

C++
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? It's not NULL and it's most probably not a valid address either. ASSERT will not catch it and your application will throw an exception.

More Macros

Here, a more advanced solution is 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 these situations.

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

C++
#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:

C++
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 cannot 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 responsibility. :)

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.


Written By
Software Developer (Senior)
Portugal Portugal
Software Smith, Blacksmith, Repeat Founder, Austrian, Asgardian.

Comments and Discussions

 
GeneralGuaranteed Multithreading Problems Pin
pg--az12-Jun-09 2:22
pg--az12-Jun-09 2:22 
GeneralThese IsBadxxx functions are dangerous! Pin
AaronJRidout31-Oct-07 5:38
AaronJRidout31-Oct-07 5:38 
GeneralRe: These IsBadxxx functions are dangerous! Pin
Andreas Saurwein31-Oct-07 5:56
Andreas Saurwein31-Oct-07 5:56 
GeneralRe: These IsBadxxx functions are dangerous! Pin
Blake Miller2-May-08 5:29
Blake Miller2-May-08 5:29 
Generalevc support Pin
Hillol Sarker12-Oct-04 22:17
Hillol Sarker12-Oct-04 22:17 
GeneralRe: evc support Pin
Liby Baby6-Jul-05 18:17
sussLiby Baby6-Jul-05 18:17 
Generalnew -> delete -> valid pointer Pin
Thomas Knauth18-Nov-02 5:14
Thomas Knauth18-Nov-02 5:14 
GeneralRe: new -> delete -> valid pointer Pin
Andreas Saurwein18-Nov-02 5:45
Andreas Saurwein18-Nov-02 5:45 
GeneralRe: new -> delete -> valid pointer Pin
Philippe Lhoste2-Dec-02 4:56
Philippe Lhoste2-Dec-02 4:56 
GeneralRe: new -> delete -> valid pointer Pin
Andreas Saurwein2-Dec-02 12:04
Andreas Saurwein2-Dec-02 12:04 
Yes, which unfortunately is optimized away in a release build. But for debug builds its a great help.
A nice value is also 0xdeadbeef, 0xbaadf00d or similar Smile | :)


I don't think this is a serious possesion, and the evil most likely comes from your hand. Colin J Davies, The Lounge

Generalsizeof(LPDWORD) Pin
martinbf22-Oct-02 1:11
martinbf22-Oct-02 1:11 
GeneralRe: sizeof(LPDWORD) Pin
Andreas Saurwein22-Oct-02 2:54
Andreas Saurwein22-Oct-02 2:54 
GeneralRe: sizeof(LPDWORD) Pin
martinbf22-Oct-02 4:47
martinbf22-Oct-02 4:47 
GeneralRe: sizeof(LPDWORD) Pin
Andreas Saurwein22-Oct-02 6:14
Andreas Saurwein22-Oct-02 6:14 
GeneralRe: sizeof(LPDWORD) Pin
martinbf22-Oct-02 20:19
martinbf22-Oct-02 20:19 
GeneralRe: sizeof(LPDWORD) Pin
Anonymous24-Oct-02 4:26
Anonymous24-Oct-02 4:26 
GeneralRe: sizeof(LPDWORD) Pin
Andreas Saurwein24-Oct-02 8:43
Andreas Saurwein24-Oct-02 8:43 
GeneralRe: sizeof(LPDWORD) Pin
Anonymous24-Oct-02 13:01
Anonymous24-Oct-02 13:01 
GeneralRe: sizeof(LPDWORD) Pin
Andreas Saurwein25-Oct-02 2:19
Andreas Saurwein25-Oct-02 2:19 
GeneralRe: sizeof(LPDWORD) Pin
Anonymous25-Oct-02 5:17
Anonymous25-Oct-02 5:17 
GeneralRe: sizeof(LPDWORD) Pin
Andreas Saurwein25-Oct-02 5:33
Andreas Saurwein25-Oct-02 5:33 
GeneralRemove MFC dependency... Pin
Nguyen Binh21-Oct-02 16:47
Nguyen Binh21-Oct-02 16:47 
GeneralRe: Remove MFC dependency... Pin
KarstenK21-Oct-02 20:42
mveKarstenK21-Oct-02 20:42 
GeneralRe: Remove MFC dependency... Pin
Andreas Saurwein21-Oct-02 22:55
Andreas Saurwein21-Oct-02 22:55 
GeneralRe: Remove MFC dependency... Pin
Nguyen Binh22-Oct-02 1:37
Nguyen Binh22-Oct-02 1:37 

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

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