Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Undefined behavior
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Examples in C and C++ == The major forms of undefined behavior in C can be broadly classified as:<ref>{{cite web|url=https://blog.regehr.org/archives/1520|title=Undefined Behavior in 2017, Embedded in Academia Blog|date=4 July 2017|author= Pascal Cuoq and John Regehr}}</ref> spatial memory safety violations, temporal memory safety violations, [[integer overflow]], strict aliasing violations, alignment violations, unsequenced modifications, data races, and loops that neither perform I/O nor terminate. In C the use of any [[automatic variable]] before it has been initialized yields undefined behavior, as does integer [[division by zero]], signed integer overflow, indexing an array outside of its defined bounds (see [[buffer overflow]]), or [[null pointer]] [[dereference operator|dereferencing]]. In general, any instance of undefined behavior leaves the abstract execution machine in an unknown state, and causes the behavior of the entire program to be undefined. Attempting to modify a [[string literal]] causes undefined behavior:<ref name="C++03 2.13.4/2">[[International Organization for Standardization|ISO]]/[[International Electrotechnical Commission|IEC]] (2003). ''[[ISO/IEC 14882|ISO/IEC 14882:2003(E): Programming Languages β C++]] Β§2.13.4 String literals [lex.string]'' para. 2</ref> <syntaxhighlight lang="cpp"> char *p = "wikipedia"; // valid C, deprecated in C++98/C++03, ill-formed as of C++11 p[0] = 'W'; // undefined behavior </syntaxhighlight> Integer [[division by zero]] results in undefined behavior:<ref name="C++03 5.6/4">[[International Organization for Standardization|ISO]]/[[International Electrotechnical Commission|IEC]] (2003). ''[[ISO/IEC 14882|ISO/IEC 14882:2003(E): Programming Languages β C++]] Β§5.6 Multiplicative operators [expr.mul]'' para. 4</ref> <syntaxhighlight lang="cpp"> int x = 1; return x / 0; // undefined behavior </syntaxhighlight> Certain pointer operations may result in undefined behavior:<ref name="C++03 5.6/5">[[International Organization for Standardization|ISO]]/[[International Electrotechnical Commission|IEC]] (2003). ''[[ISO/IEC 14882|ISO/IEC 14882:2003(E): Programming Languages - C++]] Β§5.7 Additive operators [expr.add]'' para. 5</ref> <syntaxhighlight lang="cpp"> int arr[4] = {0, 1, 2, 3}; int *p = arr + 5; // undefined behavior for indexing out of bounds p = NULL; int a = *p; // undefined behavior for dereferencing a null pointer </syntaxhighlight> In C and C++, the relational comparison of [[pointer (computer programming)|pointer]]s to objects (for less-than or greater-than comparison) is only strictly defined if the pointers point to members of the same object, or elements of the same [[array (data structure)|array]].<ref name="C++03 5.9/2">[[International Organization for Standardization|ISO]]/[[International Electrotechnical Commission|IEC]] (2003). ''[[ISO/IEC 14882|ISO/IEC 14882:2003(E): Programming Languages β C++]] Β§5.9 Relational operators [expr.rel]'' para. 2</ref> Example: <syntaxhighlight lang="cpp"> int main(void) { int a = 0; int b = 0; return &a < &b; /* undefined behavior */ } </syntaxhighlight> Reaching the end of a value-returning function (other than <code>main()</code>) without a return statement results in undefined behavior if the value of the function call is used by the caller:<ref name="C99 6.9.1/12">[[International Organization for Standardization|ISO]]/[[International Electrotechnical Commission|IEC]] (2007). ''[[ISO/IEC 9899|ISO/IEC 9899:2007(E): Programming Languages β C]] Β§6.9 External definitions'' para. 1</ref> <syntaxhighlight lang="c"> int f() { } /* undefined behavior if the value of the function call is used*/ </syntaxhighlight> Modifying an object between two [[sequence point]]s more than once produces undefined behavior.<ref>ANSI X3.159-1989 ''Programming Language C'', footnote 26</ref> There are considerable changes in what causes undefined behavior in relation to sequence points as of C++11.<ref name=":0">{{cite web|url=http://en.cppreference.com/w/cpp/language/eval_order|title=Order of evaluation - cppreference.com|work=en.cppreference.com|access-date=9 August 2016}}</ref> Modern compilers can emit warnings when they encounter multiple unsequenced modifications to the same object.<ref>{{cite web | title=Warning Options (Using the GNU Compiler Collection (GCC)) | website=GCC, the GNU Compiler Collection - GNU Project - Free Software Foundation (FSF) | url=https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html | access-date=2021-07-09}}</ref><ref>{{cite web | title=Diagnostic flags in Clang | website=Clang 13 documentation | url=https://clang.llvm.org/docs/DiagnosticsReference.html#wunsequenced | access-date=2021-07-09}}</ref> The following example will cause undefined behavior in both C and C++. <syntaxhighlight lang="c"> int f(int i) { return i++ + i++; /* undefined behavior: two unsequenced modifications to i */ } </syntaxhighlight> When modifying an object between two sequence points, reading the value of the object for any other purpose than determining the value to be stored is also undefined behavior.<ref name="C99 6.5/2">[[International Organization for Standardization|ISO]]/[[International Electrotechnical Commission|IEC]] (1999). ''[[ISO/IEC 9899|ISO/IEC 9899:1999(E): Programming Languages β C]] Β§6.5 Expressions'' para. 2</ref> <syntaxhighlight lang="c"> a[i] = i++; // undefined behavior printf("%d %d\n", ++n, power(2, n)); // also undefined behavior </syntaxhighlight> In C/C++ [[logical shift|bitwise shifting]] a value by a number of bits which is either a negative number or is greater than or equal to the total number of bits in this value results in undefined behavior. The safest way (regardless of compiler vendor) is to always keep the number of bits to shift (the right operand of the <code><<</code> and <code>>></code> [[bitwise operation|bitwise operators]]) within the range: [<code>0, [[sizeof]] value * CHAR_BIT - 1</code>] (where <code>value</code> is the left operand). <syntaxhighlight lang="c"> int num = -1; unsigned int val = 1 << num; // shifting by a negative number - undefined behavior num = 32; // or whatever number greater than 31 val = 1 << num; // the literal '1' is typed as a 32-bit integer - in this case shifting by more than 31 bits is undefined behavior num = 64; // or whatever number greater than 63 unsigned long long val2 = 1ULL << num; // the literal '1ULL' is typed as a 64-bit integer - in this case shifting by more than 63 bits is undefined behavior </syntaxhighlight>
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)