15

Consider following basic example:

#include <stdio.h>

int main(void)
{
    printf("Hi there!\n");
}

Does it invoke undefined behaviour in C89? I tried to get some sense from this question, but most upvoted answers claim that it's implementation-defined and definitely no UB here (with comments of Keith Thompson, that looks contradictory).

The spec says in §3.16 Definitions and conventions:

If a “shall” or “shall not” requirement that appears outside of a constraint is violated. the behavior is undefined. Undefined behavior is otherwise indicated in this International Standard by the words “undefined behavior” or by the omission of any explicit definition of behavior. There is no difference in emphasis among these three: they all describe “behavior that is undefined”.

and §5.1.2.2.3 Program termination:

A return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument. If the main function executes a return that specifies no value, the termination status returned to the host environment is undefined.

My understanding is that latter subclause does not cover case of missing return, as return statement in not never invoked, thus former subclause applies.

However futher reading indicates something different, §6.6.6.4 The return statement:

If a return statement without an expression is executed, and the value of the function call is used by the caller, the behavior is undefined. Reaching the } that terminates a function is equivalent to executing a return statement without an expression.

Ok, so now 5.1.2.2.3 subclause applies:

If the main function executes a return that specifies no value. the termination status returned to the host environment is undefined.

The term "termination status is undefined" does not seem to be UB, nor any specific behavior, but more like it's outside of scope of C Standard, thinking more like: "let the host environment to be worry about, we wash our hands from here". Is it correct intepretation?

Community
  • 1
  • 1
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
  • 1
    If you didn't already saw it, here are some interesting answers: http://stackoverflow.com/q/204476/3933332 – Rizier123 Jan 28 '15 at 22:32
  • 1
    [My go-to C89 draft](http://port70.net/~nsz/c/c89/c89-draft.html) doesn't match up at all with the quotes you've given. The section numbers are completely different, and the corresponding text differs as well. Of course, it is a draft, not the final standard. Nevertheless, we cannot possibly agree on an answer if we don't agree on the standard. – John Bollinger Jan 28 '15 at 22:34
  • 2
    I would read that is saying it's equivalent to calling `return` with no expression, which then per `§5.1.2.2.3` states that a `return` with no expression results in an undefined return code to the host OS. You're correct, this isn't undefined behavior per-say, as what happens is known and always the same; the program will terminate and a value will be returned to the OS as a returncode. What *is* undefined is what that value will be. So yes, I would say your interpretation is correct. – aruisdante Jan 28 '15 at 22:35
  • [It is allowed in C99](https://stackoverflow.com/a/13545299). While this doesn't answer your question regarding C89, I think from a compiler writer's point of view it would be crazy to trigger UB in C89 but have well-defined behavior in C99. This might even be considered a defect in C89. – Rufflewind Jan 28 '15 at 22:38
  • Working from the standard excerpts you provided, I say it is implicit in "the termination status returned to the host environment is undefined" that reaching the trailing `}` of `main()` results in program termination. That much therefore seems defined. I am inclined to say that it is undefined, however, whether `exit()` is called in that case, and if it is, then the value of its argument is definitely undefined. Those details are within the scope of the C standard, so the program does have undefined behavior. – John Bollinger Jan 28 '15 at 22:47

2 Answers2

4

Years ago I actually debugged issues caused by this. It gets even more interesting if you have some code paths with returns and others without.

As @aruisdante surmised in the comments, the behavior exhibited is indeed 'undefined', but the only undefined part is the value returned (it's not like many other 'undefined' situations that may crash the program).

These days this actually amounts to a security risk because the 'undefined' value returned is generally whatever happens to be in the CPU register normally used to return values (or on the stack in some implementations), which could theoretically be used to leak sensitive data.

James
  • 3,551
  • 1
  • 28
  • 38
2

I believe that intent of Standard Committee was that this termination status value is unspecified.

According to N739 draft:

and change the last sentence of subclause 5.1.2.2.3 from:

If the /main/ function executes a return that specifies no value, the termination status returned to the host environment is undefined.

to:

If the /main/ function executes a return that specifies no value, | the termination status returned to the host environment is unspecified.

[The concept of undefined value is carefully avoided elsewhere.]

You may also find in further Standards, that terminology was changed and term "unspecified" is used consequently.

I would say that it's definitely not intented to be undefined behaviour per se, but still it's impossible to decide whether it's unspecified behavior or as I said no behaviour at all. Other excerpt, that would indicate latter these is §1 Scope:

This International Standard does not specify:

  • the mechanism by which C programs are invoked for use by a data-processing system;

I would expect this also means that this International Standard does not specify how programs's termination status is handled by host environment.

Community
  • 1
  • 1
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137