20

We've all heard the warnings that if you invoke undefined behaviour in C or C++, anything at all can happen.

Is this limited to any runtime behaviour at all, or does this also include any compile-time behaviour? In particular, is a compiler, upon encountering a construct that invokes undefined behaviour, allowed to reject the code (in the absence of other requirements in the standard to do so), or even to crash?

HighCommander4
  • 50,428
  • 24
  • 122
  • 194
  • 1
    Check out the "recommended" compiler flags for GCC: -Wall -Wextra -Wconversion -pedantic. They will help you detect most of the nasty stuff... – Mihai Todor Jul 18 '12 at 16:40
  • The linker will complain if you violate the one definition rule, and that rule declaree its violation to be UB IIRC. – Xeo Jul 18 '12 at 16:40
  • @Xeo don't mention the linker:( I'm sure I'm not the only one who has much, much more trouble with linking than compiling. It often seems like linking defines 'undefined behaviour' – Martin James Jul 18 '12 at 21:47
  • Related: http://stackoverflow.com/questions/7421170/constexpr-undefined-behaviour – Flexo Nov 12 '15 at 18:26

5 Answers5

19

"You're all ignoring the actual definition and focusing on the note, The standard imposes no requirements." - @R.MartinhoFernandes

The message above was written by the given user in Lounge<C++> and makes a very valid argument; the standard doesn't impose any requirements when it comes to code that invokes undefined behavior.


! ! !

undefined-behavior stretches even to the far corner of parsing the input data (ie. code) by the compiler, as verified with the below quotations from both the C++11 and C99 standards.

To answer your question with one sentence;

  • undefined behavior is not limited to runtime execution, and it's permissible to crash during compilation "in a documented manner characteristic of the environment" 1

"in a documented manner characteristic of the environment" is a kind of odd statement, you could pretty much write a compiler documenting that it might crash upon any given code (that's invalid) to grant it the possibility to crash whenever it wants to.

1. quote from the C++11/C99 standards


###

###1.3.24 [defns.undefined]

Undefined behavior; behavior for which this International Standard imposes no requirements

[ Note:

Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data.

Permissible 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).

Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed.

end note ]


###

3.4.3 - Undefined Behavior

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

  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).

Community
  • 1
  • 1
Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
  • 5
    "in a documented manner characteristic" doesn't make sense as a fragment; it only makes sense as "in a documented manner characteristic *of the environment*". I'd read this as saying that a compiler should behave in the same way as other programs on the platform; writing to stderr on Unix, or displaying a dialog box on Windows. – ecatmur Jul 18 '12 at 17:17
  • To follow @ecatmur's comment: it doesn't seem right to say it's permitted for the compiler to *crash*, exactly. It's permitted to deliberately *terminate*. A subtle distinction, but by definition, a program should never crash by design, regardless of whether it's a C compiler. – Max Barraclough Jun 09 '20 at 21:48
10

If the behavior is undefined, the compiler could accept it, reject it, issue a warning, and according to the standard, even crash, hang or install a virus on your computer.

In practice, that does not mean if you are writing a compiler you should do those things on purpose, but you could, for example, use an algorithm which works on defined cases and crashes or hangs on undefined ones, if the performance advantage justifies it.

Still, a reputable compiler would avoid that, or at least have it very well documented.

AlexDev
  • 4,049
  • 31
  • 36
  • 2
    **-1**. this is wrong, see other answers quoting the standard (such as the one written by me with quotes from both C99 and C++11) – Filip Roséen - refp Jul 18 '12 at 16:51
  • 5
    Which part is wrong? Accept it=ignoring the situation completely, reject it=terminating translation with issuance of a diagnostic message, issue a warning=accept with issuance etc. – AlexDev Jul 18 '12 at 16:54
  • Unless you mean terminating translation=crash, which I don't think is what the OP intended. – AlexDev Jul 18 '12 at 16:56
  • it implies that the standard says that it shouldn't crash with bad input, that's how me and a few friends interpret it at least. – Filip Roséen - refp Jul 18 '12 at 16:56
  • Generally true in practice, but not necessarily the case under the standard. A compiler *can* crash when compiling code with undefined behavior and remain compliant with the C++ standard. – bwDraco Oct 08 '16 at 18:52
  • @bwDraco I Believe you and Seth are right, though I don't agree with refp's interpretation that crashing constitutes a behavior characteristic of any environment (except maybe some old versions of windows ;) ). I updated the answer accordingly. – AlexDev Oct 10 '16 at 17:57
  • @bwDraco: I think that in current versions of the Standard, if a program contains an `#error` directive that survives the preprocessor, that is supposed to terminate efforts to process the program; the Standard doesn't specify what happens after that, but quality implementations should do so. – supercat Oct 30 '16 at 21:39
2

It is not limited to run-time behavior. Per ISO/IEC 14882, first edition, 1998-09-01, 1.3.12, in a note (so non-normative): “permissible undefined behavior ranges from... to behaving during translation or programming execution in a documented manner characteristic of the environment”. In other words, the standard says the implementation may do anything the operating system (or other environment) permits, provided it is documented.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Unfortunately, it's often unclear in what cases the fact that documentation of an *environment*'s behavior constitutes documentation of implementations' behavior. It used to be widely regarded as implicitly doing so, but that is no longer fashionable. – supercat Oct 30 '16 at 21:41
1

At least some forms of Undefined Behavior may cause the act of compilation itself to behave in ways outside the jurisdiction of the Standard. For example, the authors of the Standard did not want to preclude the use of something like

#include `someProg arg`

or

#pragma exec-include "someProg arg"

as a means of running someProg with the given arguments and treat the output of such program as though it would be part of the source text. Since the the behavior of a programs invoked by such syntax would be outside the jurisdiction of the Standard, such constructs are--from the point of view of the Standard--simply regarded as invoking UB at compile time.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

I always love Standard quotes, so if that's what you're looking for, the standard defines undefined behaviour as

behavior for which this International Standard imposes no requirements

[Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior for when a program uses an erroneous construct or erroneous data. Permissible 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). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. —end note ]

And "translation" is basically going from source to the end product (assembly or whatever). So we can mix those two possibilities and get

ignoring the situation completely with unpredictable results during translation

So yes, the compiler is free to exhibit undefined behaviour during compilation as well as at runtime.

Community
  • 1
  • 1
Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • 2
    I don't see how this allows undefined behaviour at compile time. "Ignoring the situation with completely unpredictable results" seems to apply only to runtime behaviour. "Behaving during translation or program execution in a documented manner" seems to exclude a crash. – HighCommander4 Jul 18 '12 at 17:04
  • @HighCommander4 the key words are "from ... to ..." which means those are only examples and anything between the two, or any combination of the two, or whatever, can happen. – Seth Carnegie Jul 18 '12 at 17:05