Undefined Behaviour
Undefined Behaviour (UB)
Undefined behaviour (UB) refers to the behaviour of a computer program that isn’t defined or specified by the C++ standard. When a program exhibits undefined behaviour, anything can happen; there are no guarantees about how the program will behave, and it may produce
changeable or unanticipated results. UB is a result of writing code that violates the rules and constraints specified in the C++ standard.
Illustrations of situations that can lead to undefined behaviour include
- Dereferencing Null Pointers: Accessing or dereferencing a pointer that points to nullptr (a null pointer) leads to undefined behaviour.
- Out-of-bonds Array Access: Accessing elements of an array beyond its bounds (both reading and writing) leads to undefined behaviour.
- Division by Zero: Performing integer or floating-point division by zero leads to undefined behaviour.
- Uninitialized Variables: Using variables that haven’t been initiated with a value can result in undefined behaviour.
- Buffer Overflows: Writing more data into a buffer (array) than it can hold can lead to undefined behaviour and implicit security vulnerabilities.
- Use After Free: Accessing memory through a pointer after the memory has been deallocated (e.g., using a deleted pointer) leads to undefined behaviour.
- Unspecified Order of Evaluation:The order in which subexpressions are evaluated in an expression with multiple side effects may be unidentified, leading to undefined behaviour if the subexpressions depend on each other.
- Type Punning: Accessing the memory representation of an object through a pointer of a different type (type punning) leads to undefined behaviour.
It’s important to avoid undefined behaviour in C++ programs because it can lead to crashes, changeable results, and security vulnerabilities and make the code delicate to maintain and debug. The C++ standard intentionally leaves certain behaviours out to allow optimisations.
To write safe and dependable C++ code, it’s pivotal to follow the rules and guidelines outlined in the C++ standard and to use good programming practices, such as proper memory management, bounds checking, and avoiding relying on undefined behaviour for desired behaviour. Also, using ultramodern C++ features, smart pointers, and library functions can help prevent common sources of undefined behaviour.