Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can static_cast turn a non-null pointer into a null pointer?

I need to write code for a callback function (it will be called from within ATL, but that's not really important):

HRESULT callback( void* myObjectVoid )
{
    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    return myObject->CallMethod();
}

here the void* is guaranteed to be a pointer to CMyClass, so static_cast is legal. My concern is the code must be as portable (to newer versions of Visual C++ at least) as possible. So to be super-paranoic I'm inclined to check the CMyClass* pointer as well - I mean what if it turns out to be null?

    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    if( myObject == 0 ) {
       return E_POINTER;
    }

Is the second check reasonable? Is it possible for static_cast to turn a non-null pointer into a null pointer?

like image 663
sharptooth Avatar asked Aug 12 '10 14:08

sharptooth


People also ask

Does static_cast return null?

The static_cast operator converts a null pointer value to the null pointer value of the destination type.

What is the use of static_cast in C++?

The static_cast operator converts variable j to type float . This allows the compiler to generate a division with an answer of type float . All static_cast operators resolve at compile time and do not remove any const or volatile modifiers.

Can a static cast be null?

You can static_cast a null pointer - it will give you a null pointer.

Can static_cast fail at runtime?

The cast is done at run time and can fail if the underlying object does not support the target interface. If a static_cast fails, then the code does not compile (an error is issued: E2031).


2 Answers

static_cast can change the pointer value, if you cast between object parts on different offsets:

class A{ int x; }; class B{ int y; };
class C : A,B {};

C *c=new C(); 

B *b=c; 
// The B part comes after the A part in C. Pointer adjusted

C *c2=static_cast<C*>(b); 
// Pointer gets adjusted back, points to the beginning of the C part

However, "The null pointer value (4.10) is converted to the null pointer value of the destination type." (5.2.9-8), i.e. if c is NULL, then b is also NULL (and not adjusted) and thus c2 is set to NULL. The whole thing means: if static casting a non-NULL myObjectVoid yields NULL, then the value of myObjectVoid was obtained by circumventing the type system somehow. And it means, that the compiler might throw your second check away because "it can't happen anyway".

like image 133
Nordic Mainframe Avatar answered Nov 05 '22 03:11

Nordic Mainframe


No. If the pointer refers to a valid object, and the conversion is valid, then the result will also refer to a valid object, so it won't be null. If either is invalid, then the code is incorrect and the result is undefined. So the only way for valid usage to give a null result is to start with null.

In the specific case of converting between object pointers and void pointers, the standard has this to say (5.2.9/10):

A value of type "pointer to object" converted to "pointer to void" and back to the original pointer type will have its original value.

and this (4.10/3)

The result of converting a "pointer to T" to a "pointer to void" points to the start of the storage location where the object of type T resides

so the original and final object pointers will be the same, and the void pointer will be null if and only if the object pointers are.

like image 44
Mike Seymour Avatar answered Nov 05 '22 04:11

Mike Seymour