What is undefined behavior, unspecified and defined by implementation?

Asked

Viewed 677 times

16

What is the difference between the three terms "undefined behavior", "unspecified behavior" and "behavior defined by implementation"?

Why do they exist in these forms?

1 answer

9


Safer languages try to avoid these behaviors. In languages where it is expected the best of performance, flexibility and use of architecture is more common to leave some things open. This is the case of C and C++.

First understand that these things fit in language specification. And the implementation may or may not do differently, just as one of the terms already indicates.

Undefined behavior

It is a situation in which language does not determine what should be done, does not say that it should generate error, or that it should run in a specific way, does not have a solution to it. It is expected that it will be useful in some scenario in the form used and that the programmer knows the difficulties existing and avoid in other scenarios.

So we can say that it is a valid syntax without indicating clearly what will happen there.

A well-known example is access to information that is not desired. This occurs:

  • when reading an element of an array beyond its limits
  • tries to write beyond the boundary of the vector, structure or scalar type
  • when dereferencing a null or value pointer that was not meant to be a pointer
  • accesses an area of memory that contained the desired information for a while, but the lifespan of hers expired.
  • among others

Some odd expressions can generate undefined behavior. A well-known example is i++ + ++i. The syntax is ambiguous. Of course, language could have defined that this is a mistake and say how to treat such a case or have a rule to make it unambiguous, but they chose not to. Probably unintentionally at first, and purposely afterwards to avoid breaking compatibility with any existing code that makes use.

There are cases where the specification clearly says that the behavior is undefined. It says that it is not to have a rule that regulates it. This does not prevent a specific situation from always having the same result. It depends on the type of undefined behavior. The fact is that any behavior you have is in accordance with the language specification, although it’s probably a mistake to do that. The idea is that the implementation (compiler) let do wrong even.

The C language specification speaks this clearly. C++ has similar definitions:

3.4.3 1 Undefined behavior behavior, upon use of a nonportable or erroneous program Construct or of erroneous data, for which this International Standard imposes no

2 NOTE Possible Undefined behavior ranges from ignoring the Situation completely with unpredictable Results, to behaving During Translation or program Execution in a documented Manner characteristic of the Environment (with or without the Issuance of a Diagnostic message), to terminating a Translation or Execution (with the Issuance of a Diagnostic message).

3 EXAMPLE An example of Undefined behavior is the behavior on integer overflow.

Unspecified behaviour

Here changes a little. The implementation needs to address the situation to generate a defined behavior, but what it will be is the implementation problem and only the implementation problem. She doesn’t need to inform anyone how this is done. It doesn’t even need to be consistent across versions.

A typical example:

void f(int n, int m);
int f1() {
    return 1;
}
int f2() {
    return 2;
}
f(f1(), f2());

It is not specified which of the two functions should be called before. Each compiler can do as they please, at any time, as long as they do something valid.

3.4.4 1 unspecified behavior use of an unspecified value, or other behavior Where this International Standard provides two or more Possibilities and imposes no further

2 EXAMPLE An example of unspecified behavior is the order in which the Arguments to a Function are evaluated.

Behavior defined by the implementation

Here we come to a better point. The specification lets the implementation do as it wants, but this should be officially declared (documentation) for the user (the programmer) to know what will happen. It is expected to have some compatibility between versions, or at least a way to choose between the behaviors defined if it is necessary to change.

An example:

int *o = malloc(0 * sizeof *o);

I put in the Github for future reference.

Your compiler (its library) must document whether it will return a null or a unique valid pointer to a location that nothing will be reserved for.

3.4.1 1 implementation-defined behavior unspecified behavior Where each implementation Documents how the Choice is made

2 EXAMPLE An example of implementation-defined behavior is the Propagation of the high-order bit when a Signed integer is shifted right.

Defined behaviour

In fact most behaviors are defined by the specification and for an implementation to conform to the specification needs to do exactly what it tells it to do. Good. Because it’s normal, there’s no definition of it.

If your code needs to be portable, only defined behaviors should be used, or the other three forms of behavior need to be properly handled in each individual build environment.

Completion

Although it is very strong for C and C++, the terms can be used in other languages.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.