C++26 has introduced erroneous behavior in addition to undefined, unspecified, and implementation-defined behavior (see Undefined, unspecified and implementation-defined behavior). How is this new construct different from the existing kinds of behavior, and why has it been added to the C++ standard?
What is erroneous behavior? How is it different from undefined behavior?
1.7k views Asked by Jan Schultke At
1
There are 1 answers
Related Questions in C++
- Best way to make an HABTM association via console
- undefined method `namespace' for main:Object (NoMethodError) - active record / rakefile
- Ruby destroy is not working? Or objects still present?
- Trying to set the value of an input with mechanize
- How to split the logic in a ruby game
- How can I monitor an endpoint's status with Ruby?
- Why can a private class method be explicitly invoked in Ruby?
- Rails - Ajax do not work properly on production server
- syntax error, unexpected kEND
- Carrierwave file upload with different file types
Related Questions in UNDEFINED-BEHAVIOR
- Best way to make an HABTM association via console
- undefined method `namespace' for main:Object (NoMethodError) - active record / rakefile
- Ruby destroy is not working? Or objects still present?
- Trying to set the value of an input with mechanize
- How to split the logic in a ruby game
- How can I monitor an endpoint's status with Ruby?
- Why can a private class method be explicitly invoked in Ruby?
- Rails - Ajax do not work properly on production server
- syntax error, unexpected kEND
- Carrierwave file upload with different file types
Related Questions in C++26
- Best way to make an HABTM association via console
- undefined method `namespace' for main:Object (NoMethodError) - active record / rakefile
- Ruby destroy is not working? Or objects still present?
- Trying to set the value of an input with mechanize
- How to split the logic in a ruby game
- How can I monitor an endpoint's status with Ruby?
- Why can a private class method be explicitly invoked in Ruby?
- Rails - Ajax do not work properly on production server
- syntax error, unexpected kEND
- Carrierwave file upload with different file types
Related Questions in ERRONEOUS-BEHAVIOR
- Best way to make an HABTM association via console
- undefined method `namespace' for main:Object (NoMethodError) - active record / rakefile
- Ruby destroy is not working? Or objects still present?
- Trying to set the value of an input with mechanize
- How to split the logic in a ruby game
- How can I monitor an endpoint's status with Ruby?
- Why can a private class method be explicitly invoked in Ruby?
- Rails - Ajax do not work properly on production server
- syntax error, unexpected kEND
- Carrierwave file upload with different file types
Popular Questions
- How do I undo the most recent local commits in Git?
- How can I remove a specific item from an array in JavaScript?
- How do I delete a Git branch locally and remotely?
- Find all files containing a specific text (string) on Linux?
- How do I revert a Git repository to a previous commit?
- How do I create an HTML button that acts like a link?
- How do I check out a remote Git branch?
- How do I force "git pull" to overwrite local files?
- How do I list all files of a directory?
- How to check whether a string contains a substring in JavaScript?
- How do I redirect to another webpage?
- How can I iterate over rows in a Pandas DataFrame?
- How do I convert a String to an int in Java?
- Does Python have a string 'contains' substring method?
- How do I check if a string contains a specific word?
Popular Tags
Trending Questions
- UIImageView Frame Doesn't Reflect Constraints
- Is it possible to use adb commands to click on a view by finding its ID?
- How to create a new web character symbol recognizable by html/javascript?
- Why isn't my CSS3 animation smooth in Google Chrome (but very smooth on other browsers)?
- Heap Gives Page Fault
- Connect ffmpeg to Visual Studio 2008
- Both Object- and ValueAnimator jumps when Duration is set above API LvL 24
- How to avoid default initialization of objects in std::vector?
- second argument of the command line arguments in a format other than char** argv or char* argv[]
- How to improve efficiency of algorithm which generates next lexicographic permutation?
- Navigating to the another actvity app getting crash in android
- How to read the particular message format in android and store in sqlite database?
- Resetting inventory status after order is cancelled
- Efficiently compute powers of X in SSE/AVX
- Insert into an external database using ajax and php : POST 500 (Internal Server Error)
Erroneous behavior is "buggy" or "incorrect" behavior, as explained by P2795: Erroneous behavior for uninitialized reads. This proposal introduced erroneous behavior into C++26, turning previously undefined behavior into erroneous behavior.
The most notable difference is that undefined behavior has no limit as to what the program may do, including jumping into "random" functions, accessing memory that shouldn't be accessed, and other effects which are detrimental to security. Erroneous behavior is formally ([defns.erroneous]):
It may be diagnosed through warnings, run-time errors, etc.; formally, [intro.abstract] p4.1.2 explains:
Motivation
Unfortunately, a substantial amount of C++ code is not bug-free, and many bugs can be harmful to security. An obvious example is this:
If
f
takes up some space on the stack, an attacker could make sure that the memory on the stack prior to executing this code has a value of their choice.f()
would thus allow an attacker to jump to any instruction in the program they want. There are many more such cases of CWE-457: Use of Uninitialized Variable.Simply making this code "correct" by initializing the function pointer to
nullptr
by default also wouldn't make sense, since there is clearly a bug here.f
should have been initialized and the compiler should bring our attention to that fact if we forgot to initialize it before callingf
, storing it somewhere, etc. We wouldn't want this bug to simply be "swept under the rug".How does erroneous behavior work?
Erroneous behavior starts with an erroneous value, which e.g. is produced when leaving a variable uninitialized. On a side note, the pre-C++26 behavior can be reproduced using the
[[indeterminate]]
attribute:As explained above, undefined behavior could do anything here, including jumping into a function other than
f
, whereasf(erron)
should always have defined behavior, but should be diagnosed at some point.Erroneous vs. ill-formed
Erroneous behavior may seem similar to ill-formed programs, since both should result in a diagnostic (see also [intro.compliance.general] p8).
However, erroneous behavior comes into effect during program execution, whereas a program is ill-formed during translation (compilation). For example:
Erroneous behavior in constant expressions
Unlike undefined behavior, erroneous behavior always disqualifies expressions from being constant expressions ([expr.const]). Note that undefined behavior behaves the same in most cases, but e.g. failed Preconditions in most of the standard library or failed
[[assume]]
attributes can still result in UB inside of constant expressions.Also, a
constexpr
object cannot have erroneous value:In C++23, this would have also been ill-formed because
x
would have had indeterminate value.The broader picture
In general, C++ developers and the C++ committee are pushing the language into a "safer" direction. As part of that, a large amount of undefined behavior could be turned into erroneous behavior over the coming years.
In some cases, there is already a highly motivated proposal for it, such as P2973: Erroneous behavior for missing return from assignment. Some other cases of undefined behavior like signed integer overflow, division by zero, etc. could be made erroneous.
Harder-to-diagnose forms of UB such such as data races or invalid down-casts (with
static_cast
) will likely remain undefined, perhaps indefinitely.The cost of erroneous behavior
Compilers increasingly rely on undefined behavior for the purpose of optimizations. For example:
The compiler can optimize this down to:
If
i
was anything other than0
, the arrayarr
would be accessed out of bounds, which is undefined behavior. The compiler is allowed to assume that UB simply doesn't happen and optimize accordingly. If accessing arrays out of bounds was turned into erroneous behavior, the compiler would be encouraged to add a run-time bounds check to the array access and terminate the program ifi
is not0
.In conclusion, erroneous behavior isn't "free"; it comes at a performance cost. Erroneous behavior is typically added to the C++ standard where the security risk of undefined behavior is significant, and where the cause of undefined behavior is not commonly used for optimizations.