Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly is warning C4718 (of Visual Studio)?

msdn link

text here:

'function call' : recursive call has no side effects, deleting

A function contains a recursive call, but otherwise has no side effects. A call to this function is being deleted. The correctness of the program is not affected, but the behavior is. Whereas leaving the call in could result in a runtime stack overflow exception, deleting the call removes that possibility.

The code causing this warning is:

template<class Key, class Value>
void Map<Key, Value>::Clear(NodeType* pNode)
{
    ((Key*) (pNode->m_key))->~Key();
    ((Value*) (pNode->m_item))->~Value();

    NodeType* pL = pNode->GetLeftChild();
    NodeType* pR = pNode->GetRightChild();
    if (pL != &m_dummy)
    {
        Clear(pL);
    }
    if (pR != &m_dummy)
    {
        Clear(pR);
    }
}

and 1 more point: this warning only happens in release build (/Ox)

What is this warning? Thanks!

like image 798
Marson Mao Avatar asked Dec 26 '22 10:12

Marson Mao


2 Answers

I'll bet it occurs when ~Key and ~Value are no-ops. The compiler will notice that there is literally nothing else that this function tries to do, so it entirely eliminates this function.

like image 61
MSalters Avatar answered Dec 28 '22 09:12

MSalters


For starters, the warning only happens in a release build because it's the result of an optimization, and the optimizer only runs during release builds.

The optimizer is allowed to restructure or eliminate code, including recursive calls, if it can prove that that will not change the program behavior. There is probably some data-dependent path where one or both calls to Clear() for the left and right nodes would have no effect.

Edit: As @MSalters points out, it is more likely that the destructors for Key and Value are no-ops -- as they would be if Key and Value are both plain-old-data structures or simple types, since the destructors are the only side-effect possible from the function as written.

Edit 2: instead of using placement new, why not use the : initializer?

template struct Map<typename Key, typename Value> {
    Key key;
    Value value;

    Map(Key k, Value v) : key(k), value(v) {}
}
like image 24
Sam Mikes Avatar answered Dec 28 '22 10:12

Sam Mikes