Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What harsh examples are there showing C-style casts are bad?

Tags:

c++

casting

Recently I found a great example of why C-style casts are bad. We start with a following class implementing multiple COM interfaces (I have two for brevity, but there can be ten in real life):

class CMyClassInitial : public IInterface1, public IInterface2 {
    //declarations omitted
};

HRESULT CMyClassInitial::QueryInterface(REFIID iid, void** ppv)
{
    if( ppv == 0 ) {
       return E_POINTER;
    }
    *ppv = 0;
    if( iid == __uuidof(IUnknown) || iid == __uuidof(IInterface1) ) {
       *ppv = (IInterface1*)this;
    } else if( iid == __uuidof(IInterface2) ) {
       *ppv = (IInterface2*)this;
    } else {
       return E_NOINTERFACE;
    }
    AddRef();
    return S_OK;
}

The above implementation uses C-casts for adjusting pointers to account for multiple inheritance. They even work as static_casts - this pointer value will be properly adjusted.

Now we copy-paste (or should I say reuse code of?) the same QueryInterface() implementation to some other very similar class.

class CMyClassModified : public IInterface1 {
    //declarations omitted
};

and leave the implementation the same. The new class doesn't inherit from IInterface2 anymore but

} else if( iid == __uuidof(IInterface2) ) {
*ppv = (IInterface2*)this;
}

will compile just fine and C-style cast will act as reinterpret_cast - this pointer value will be copied unchanged. The caller will obtain a pointer to an object that doesn't actually implement IInterface2 - straight way to undefined behavior. Such problems can be hard to spot in a huge database and when there're many (not two as in my example) interfaces.

If static_cast was used that would not have happened - the compiler would emit an error trying to compile

*ppv = static_cast<IInterface2*>(this);

IMO that's a harsh enough example of how using C-style casts can cause serious problems.

What other examples are there?

like image 790
sharptooth Avatar asked Feb 03 '11 10:02

sharptooth


1 Answers

This FAQ item sums up why C-casts are bad.

Any C-style cast is potentiality a bomb, since they are hiding conversion warnings and errors by silencing the compiler.

Since you wanted an example, here it is:

int main()
{
    float a = 0.123;
    double *b = ( double* ) &a;
    *b = 0.123;
}
like image 137
BЈовић Avatar answered Sep 29 '22 22:09

BЈовић