Are there valid “use cases” for Undefined Behavior?

I found a piece of code that has UB, and they told him to leave it in the code with a comment that states that it is UB. Only using MSVC2012.

The code itself has a raw array of Foo objects, and then passes that array to char* using reinterpret_cast<char*> , and then calls delete casted_array (for example, this does not delete []).

Like this:

 Foo* foos = new Foo[500]; char* CastedFoos = reinterpret_cast<char*>(foos); delete CastedFoos; 

In standard 5.3.5 / 3, this is clearly Undefined Behavior.

Apparently, this code does what it does to avoid having to call destructors as optimizations.

I wondered if there are places where leaving UB in the code can be considered valid?

Also, as far as I can tell, leaving the above in the code not smart, am I right?

+4
source share
2 answers

The C ++ standard defines "undefined behavior" as follows:

for which this standard does not impose requirements

So, if you want your code to be portable for different compilers and platforms, your code should not depend on undefined behavior, since programs (which are produced by different compilers that compile your code) can change in these cases.

If you do not care about portability, then you should check to see if your compiler complies with how it behaves in the circumstances of interest. If he does not document what he is doing (and this is not necessary), be careful that the compiler can change what it is doing without warning between different versions. Also note that its behavior can be non-deterministic. So, for example, this can lead to the collapse of 1% of the time, which you may not notice during special testing, but will come back and bite you later when it starts production. Therefore, even if you use the same compiler, it may still be a bad idea to depend on undefined behavior.

As for your specific example, you can rewrite it to achieve the same effect (without calling the destructor, but fixing the memory) so that it does not lead to undefined behavior. Select a std::aligned_storage to hold the Foo array, call the new placement to build the Foo array in aligned_storage , and then when you want to free the array, release aligned_storage without deleting the placement.

Of course, this is still a terrible design, it might cause a memory leak or other problems depending on what Foo::~Foo() should have done, but at least it's not UB.

+6
source

It totally depends on your perspective.

Take an extreme example: in C ++ 03, threads were undefined. Once you had multiple threads, the behavior of your program was no longer defined by the C ++ standard.

And yet, most people would say that topics are helpful.

Of course, multithreading may have been UB in accordance with the C ++ standard, but individual compilers did not consider it as undefined. They provided an additional guarantee that multithreading would work the way you expected.

Speaking of C ++ in the abstract, UB has no use. How could this be? You do not know what can or will happen.

But in specific applications, specific code compiled by specific compilers to work on specific operating systems, you may sometimes know that part of UB (1) is safe and (2) ends up with some kind of positive effect.

+7
source

All Articles