Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which issues have you encountered due to sequence points in C and C++?

Below are two common issues resulting in undefined behavior due to the sequence point rules:

a[i] = i++; //has a read and write between sequence points
i = i++;   //2 writes between sequence points

What are other things you have encountered with respect to sequence points?

It is really difficult to find out these issues when the compiler is not able to warn us.

like image 327
yesraaj Avatar asked Nov 30 '22 07:11

yesraaj


2 Answers

A variation of Dario's example is this:

void Foo(shared_ptr<Bar> a, shared_ptr<Bar> b){ ... }

int main() {
  Foo(shared_ptr<Bar>(new Bar), shared_ptr<Bar>(new Bar));
}

which might leak memory. There is no sequence point between the evaluation of the two parameters, so not only may the second argument be evaluated before the first, but both Bar objects may also be created before any of the shared_ptr's

That is, instead of being evaluated as

Bar* b0 = new Bar();
arg0 = shared_ptr<Bar>(b0);
Bar* b1 = new Bar();
arg1 = shared_ptr<Bar>(b1);
Foo(arg0, arg1);

(which would be safe, because if b0 gets successfully allocated, it gets immediately wrapped in a shared_ptr), it may be evaluated as:

Bar* b0 = new Bar();
Bar* b1 = new Bar();
arg0 = shared_ptr<Bar>(b0);
arg1 = shared_ptr<Bar>(b1);
Foo(arg0, arg1);

which means that if b0 gets allocated successfully, and b1 throws an exception, then b0 will never be deleted.

like image 77
jalf Avatar answered Dec 01 '22 20:12

jalf


There are some ambigous cases concerning the order of execution in parameter lists or e.g. additions.

#include <iostream>

using namespace std;

int a() {
    cout << "Eval a" << endl;
    return 1;
}

int b() { 
    cout << "Eval b" << endl;
    return 2;
}

int plus(int x, int y) {
    return x + y;
}

int main() {

    int x = a() + b();
    int res = plus(a(), b());

    return 0;
}

Is a() or b() executed first? ;-)

like image 25
Dario Avatar answered Dec 01 '22 22:12

Dario