Does an expression with undefined behaviour that i

2019-02-08 01:21发布

In many discussions about undefined behavior (UB), the point of view has been put forward that in the mere presence in a program of any construct that has UB in a program mandates a conforming implementation to do just anything (including nothing at all). My question is whether this should be taken in that sense even in those cases where the UB is associated to the execution of code, while the behaviour (otherwise) specified in the standard stipulates that the code in question should not be executed (and this possibly for specific input to the program; it might not be decidable at compile time).

Phrased more informally, does the smell of UB mandate a conforming implementation to decide that the whole program stinks, and refuse to execute correctly even the parts of the program for which the behaviour is perfectly well defined. An example program would be

#include <iostream>

int main()
{
    int n = 0;
    if (false)
      n=n++;   // Undefined behaviour if it gets executed, which it doesn't
    std::cout << "Hi there.\n";
}

For clarity, I am assuming the program is well-formed (so in particular the UB is not associated to preprocessing). In fact I am willing to restrict to UB associated to "evaluations", which clearly are not compile-time entities. The definitions pertinent to the example given are, I think,(emphasis is mine):

Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread (1.10), which induces a partial order among those evaluations

The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either ... or a value computation using the value of the same scalar object, the behavior is undefined.

It is implicitly clear that the subjects in the final sentence, "side effect" and "value computation", are instances of "evaluation", since that is what the relation "sequenced before" is defined for.

I posit that in the above program, the standard stipulates that no evaluations occur for which the condition in the final sentence is satisfied (unsequenced relative to each other and of the described kind) and that therfore the program does not have UB; it is not erroneous.

In other words I am convinced that the answer to the question of my title is negative. However I would appreciate the (motivated) opinions of other people on this matter.

Maybe an additional question for those who advocate an affirmative answer, would that mandate that the proverbial reformatting of your hard drive might occur when an erroneous program is compiled?

Some related pointers on this site:

8条回答
我欲成王,谁敢阻挡
2楼-- · 2019-02-08 01:42

Deciding whether a program will perform an integer division by 0 (which is UB) is in general equivalent the halting problem. There is no way a compiler can determine that, in general. And so the mere presence of possible UB can not logically affect the rest of the program: a requirement to that effect in the standard, would require each compiler vendor to provide a halting problem solver in the compiler.

Even simpler, the following program has UB only if the user inputs 0:

#include <iostream>
using namespace std;

auto main() -> int
{
    int x;
    if( cin >> x ) cout << 100/x << endl;
}

It would be absurd to maintain that this program in itself has UB.

Once the undefined behavior occurs, however, then anything can happen: the further execution of code in the program is then compromised (e.g. the stack might have been fouled up).

查看更多
乱世女痞
3楼-- · 2019-02-08 01:42

In the general case the best we can say here is that it depends.

One case where the answer is no, happens when dealing with indeterminate values. The latest draft clearly makes it undefined behavior to produce an indeterminate value during an evaluation with some exceptions but the code sample clearly shows how subtle it could be:

[ Example:

int f(bool b) {
  unsigned char c;
  unsigned char d = c; // OK, d has an indeterminate value
  int e = d;           // undefined behavior
  return b ? d : 0;    // undefined behavior if b is true
}

end example ]

so this line of code:

return b ? d : 0;

is only undefined if b is true. This seems to be the intuitive approach and seems to be how John Regehr sees it as well, if we read It’s Time to Get Serious About Exploiting Undefined Behavior.

In this case the answer is yes, the code is erroneous even though we are not calling the code invoking undefined behavior:

constexpr const char *str = "Hello World" ;      

constexpr char access()
{
    return str[100] ;
}

int main()
{
}

clang chooses to make access erroneous even though it is never invoked (see it live).

查看更多
登录 后发表回答