# What Every C Programmer Should Know About Undefined Behavior #2/3

DevFeed: [What Every C Programmer Should Know About Undefined Behavior #2/3](<https://devfeed.tech/articles/what-every-c-programmer-should-know-about-undefined-behavior-2-3-42862.md>)

Original publisher: [Read original article](<https://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html>)

Author: Chris Lattner

Published: 2011-05-14T12:33:00Z

Content type: article

Language: en

Sources: [The LLVM Project Blog](<https://devfeed.tech/sources/the-llvm-project-blog.md>)

Topics: [C](<https://devfeed.tech/topics/c.md>), [undefined\_behavior](<https://devfeed.tech/topics/undefined-behavior.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [bug](<https://devfeed.tech/topics/bug.md>), [Linux Kernel](<https://devfeed.tech/topics/linux-kernel.md>)

Tags: [bug](<https://devfeed.tech/tags/bug.md>), [c](<https://devfeed.tech/tags/c.md>), [clang](<https://devfeed.tech/tags/clang.md>), [code](<https://devfeed.tech/tags/code.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [linux-kernel](<https://devfeed.tech/tags/linux-kernel.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [undefined-behavior](<https://devfeed.tech/tags/undefined-behavior.md>)

## AI overview

This article explains how undefined behavior in C and C++ enables compiler optimizations but can produce surprising results. It examines how optimization order, null-check elimination, dead-code elimination, and inlining can change code behavior, including an example based on an exploitable Linux kernel bug.

## Source excerpt

In Part 1of our series, we discussed what undefined behavior is, and how it allows C and C++ compilersto produce higher performance applications than "safe" languages. This post talks about how"unsafe" C really is, explaining some of the highly surprising effects that undefined behaviorcan cause. In Part#3, we talk about what friendly compilers can do to mitigate some of the surprise, evenif they aren't required to. I like to call this "Why undefined behavior is often a scary and terrible thing for Cprogrammers". :-) Translation available in: Japanese,and Spanisha>.Interacting Compiler Optimizations Lead to Surprising Results A modern compiler optimizer contains many optimizations that are run in specific orders, sometimes iterated, and change as the compiler evolves over time (e.g. new releases come out). Also, different compilers often have substantially different optimizers. Because optimizations run at different stages, emergent effects can occur due to previous optimizations changing the code. Lets take a look at a silly example (simplified from an exploitable bug that was found in the Linux Kernel) to make this more concrete: void contains_null_check(int *P) { int dead = *P; if (P == 0) return; *P = 4; } In this example, the code "clearly" checks for the null pointer. If the compiler happens to run "Dead Code Elimination" before a "Redundant Null Check Elimination" pass, then we'd see the code evolve in these two steps: void contains_null_check_after_DCE(int *P) { //int dead = *P; // deleted by the optimizer. if (P == 0) return; *P = 4; } and then: void contains_null_check_after_DCE_and_RNCE(int *P) { if (P == 0) // Null check not redundant, and is kept. return; *P = 4; } However, if the optimizer happens to be structured differently, it could run RNCE before DCE. This would give us these two steps: void contains_null_check_after_RNCE(int *P) { int dead = *P; if (false) // P was dereferenced by this point, so it can't be null return; *P = 4; } and then dead co