user1149438
user1149438

Reputation: 41

C++ Short Circuit Evaluation

Maybe I am missing something rather simple, but I am getting a crash when I dereference a pointer even though I check the point at the very beginning of the expression.

if( var1 &&
    bool1 || bool2 &&
    var1->DoSomething() )
{

}

var1 is a null pointer, but Var1->Dosomething() is still being called. My understanding is that the && and the || operator in C++ are short circuit so if var1 was null then it would just terminate at the very beginning. Or is there something else I am missing?

Upvotes: 3

Views: 615

Answers (3)

celtschk
celtschk

Reputation: 19721

Since && has higher precedence than ||, your expression is parsed as (var1 && bool1) || (bool2 && var1->DoSomething()). Now since var1 is a null pointer, short circuit evaluation means that bool1 is not evaluated, and the left hand side of || evaluates as false. Thus to find out the value of the expression, the right hand side has to be evaluated (i.e. short-circuit evaluation does not kick in here!). The right hand side of || is bool2 && var1->DoSomething(), thus if bool2 is true, var1->DoSomething() will be evaluated. Note also that even for var1 non-null, the result of the eexpression will not always be what you probably expected.

Upvotes: 2

ted
ted

Reputation: 4975

Simple. && has higher precedence so your expression reads:

if( ( var1 && bool1 ) || ( bool2 && var1->DoSomething()) )

try

if( var1 && ( bool1 || bool2 ) && var1->DoSomething() )

otherwise the first expression car1 && bool1 fails and the second expression is evaluated. since bool2 returns true apparently your pointer is dereferenced if bool2 is true.

look here for a precedencelist: http://en.cppreference.com/w/cpp/language/operator_precedence or use google.

Upvotes: 1

Armen Tsirunyan
Armen Tsirunyan

Reputation: 132994

Operator precedence is the key here. Because && has higher precedence than ||, your expression is equivalent to

(var1 && bool1) || (bool2 && var1->DoSomething() )

So, since var1 evaluates to false, bool1 is not evaluated and (var1 && bool1) yields false, therefore (bool2 && var1->DoSomething()) has to be evaluated. And if bool2 happens to be true, then var1->DoSomething() will also be evaluated, resulting in undefined behavior.

Just add some parentheses (for the specific expression tree that you require) and you'll be fine.

Upvotes: 12

Related Questions