Can an implementation specify undefined behavior

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-03 19:14:46

问题


3.4.1
1 implementation-defined behavior
unspecified behavior where each implementation documents how the choice is made

Can an implementation specify that, implementation-defined behavior is undefined behavior in cases where undefined behavior is a possible outcome?

For example:

6.3.1.3 Signed and unsigned integers
3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

So as long as it is documented, can this result be undefined by the implementation and cause undefined behavior, or it must have a defined result for that implementaion?


回答1:


No, semantically this is not possible. Undefined behavior is what the term states, behavior that is not defined by the standard. If the standard requests implementation defined behavior, it explicitly request the implementation to specify what it does when a certain error occurs.

undefined behavior

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

So an implementation could say "under that and that circumstances this implementation raises a blurb signal" but it can't say "under that and that circumstances we don't tell you what we are doing".

Don't mystify undefined behavior as something that will happen or even as something that can be defined.




回答2:


You can find a more detailed explanation of what "implementation defined" is intended to mean in the C Rationale - not a standard document per se, but a good reference.

In chapter 1.6 Definition of terms:

Implementation-defined behavior gives an implementor the freedom to choose the appropriate approach, but requires that this choice be explained to the user. Behaviors designated as implementation-defined are generally those in which a user could make meaningful coding decisions based on the implementation definition. Implementors should bear in mind this criterion when deciding how extensive an implementation definition ought to be. As with unspecified behavior, simply failing to translate the source containing the implementation-defined behavior is not an adequate response.

You can't make a "reasonable coding decision" based on undefined behavior.

The C FAQ (again, not a standard, but a well-know reference) is quite clear too:

implementation-defined: The implementation must pick some behavior; it may not fail to compile the program. (The program using the construct is not incorrect.) The choice must be documented. The Standard may specify a set of allowable behaviors from which to choose, or it may impose no particular requirements

Neither unspecified and implementation-defined behaviors are errors - compiler can't fail the translation. They are meant to give the implementation options to produce optimal code for the targeted environment.




回答3:


The assignment of integers to smaller types is something of an oddball, since the standard clearly recognizes that some implementations may trap, but--uniquely--it requires that the trapping abide by the rules of signals; the decision to impose that requirement here but not elsewhere is somewhat curious, since in many cases it would impede what would otherwise be a straightforward optimization--replacing a signed integer variable whose type shorter than int, and whose address is never taken, with an int.

Nonetheless, for whatever reasons, the authors of the standard have gone out of their way to forbid that optimization. [Note: If I were in charge of the standard, I would specify that an explicit cast to a shorter integer type would yield a value which when cast to an unsigned type of the same size would yield the same result as casting the value directly whenever such a value exists, but that a store of an oversized value directly to an lvalue without a cast would not be thus constrained; I didn't write the standard, though].

It's ironic, actually: given:

uint64t signedpow(int32_t n, uint32_t p) {
  uint64_t result;
  while(p--) { n*=n; result+=n; }
  return result;
}
uint64t unsignedpow(uint32_t n, uint32_t p) {
  uint64_t result;
  while(p--) { n*=n; result+=n; }
  return result;
}

On a platform where int is 32 bits, the latter would have defined semantics for all values of n and p, while the former would not, but on a platform where int is 64 bits, the reverse would be true. A compiler for a typical 64-bit platform which didn't want to waste code on some other defined behavior would be required by the standard to mask off and sign-extended the signed n after each multiplication, but with some unsigned values the compiler could do anything it wanted, including going back in time and pretending that no implementation would ever promise to always perform half-sized unsigned multiplies in a fashion consistent with modular arithmetic.




回答4:


As per C11 standard, chapter 3.4.1,

implementation-defined behavior

unspecified behavior where each implementation documents how the choice is made

So, each implementation has to make a choice. Otherwise, it won't be conforming. Thus, we can say, it must have a defined result for that implementaion. That can be either of the below

  • a defined behavior, specific to that implementation, which will be exercised if the instruction is encountered.
  • a defined signal which will be raied if the instrcution is encountered. (Mostly, saying that cannot be handled.)

Related:

  1. From C99 Rationale Document, Chapter 3, (emphasis mine)

Implementation-defined behavior gives an implementor the freedom to choose the appropriate approach, but requires that this choice be explained to the user. Behaviors designated as implementation-defined are generally those in which a user could make meaningful coding decisions based on the implementation’s definition. Implementors should bear in mind this criterion when deciding how extensive an implementation definition ought to be. As with unspecified behavior, simply failing to translate the source containing the implementation defined behavior is not an adequate response.

Now, nobody can take "meaningful coding decisions" based on undefined behavior.

  1. From C FAQ, Question 11.33,

implementation-defined: The implementation must pick some behavior; it may not fail to compile the program. (The program using the construct is not incorrect.) The choice must be documented. The Standard may specify a set of allowable behaviors from which to choose, or it may impose no particular requirements.

The first sentence contains must, same as I mentioned before in my answer.



来源:https://stackoverflow.com/questions/30190011/can-an-implementation-specify-undefined-behavior

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!