Ton*_*ion 4 undefined-behavior c++11
我找到了一段有UB的代码,并被告知将其留在代码中,注释表明它是UB.仅使用MSVC2012.
代码本身有一个原始的Foo对象数组,然后将该数组转换为char*with reinterpret_cast<char*>,然后调用它delete casted_array(就像这样,而不是delete []).
像这样:
Foo* foos = new Foo[500];
char* CastedFoos = reinterpret_cast<char*>(foos);
delete CastedFoos;
Run Code Online (Sandbox Code Playgroud)
根据标准5.3.5/3,这显然是未定义的行为.
显然,这段代码可以完成它所做的工作,以避免将析构函数称为优化.
我想知道,实际上是否存在将UB留在代码中的地方有效?
另外,就我而言,在代码中留下上述内容并不聪明,我是对的吗?
这完全取决于你的观点.
举一个极端的例子:在C++ 03中,线程是未定义的行为.只要有多个线程,程序的行为就不再由C++标准定义.
然而,大多数人会说线程很有用.
当然,根据C++标准,多线程可能是UB,但是个别编译器并没有将其视为未定义.他们提供额外保障,在多线程是要工作,正如你所期望.
在抽象地谈论C++时,UB没有任何用处.怎么可能呢?你不知道会发生什么或者会发生什么.
但是在特定应用程序中,特定编译器编译的特定代码在特定操作系统上运行时,您有时可能知道一块UB是(1)安全的,(2)最终会产生某种有益效果.
C++标准定义了"未定义的行为",如下所示:
本标准没有要求的行为
因此,如果您希望您的代码可以移植到不同的编译器和平台,那么您的代码不应该依赖于未定义的行为,因为在这些情况下,程序(由编译代码的不同编译器生成的程序)可能会有所不同.
如果您不关心可移植性,那么您应该检查您的编译器是否记录了它在感兴趣的情况下的行为.如果它没有记录它的作用(并且它没有必要),请注意编译器可以在不同版本之间没有警告的情况下改变它的作用.还要注意其行为可能是不确定的.因此,例如,它可能会在1%的时间内崩溃,您可能在临时测试中没有注意到,但是当它投入生产时会回来并咬你.因此,即使您使用的是一个编译器,依赖于未定义的行为仍然是一个坏主意.
关于您的具体示例,您可以重写它以实现相同的效果(不调用析构函数,但回收内存),不会导致未定义的行为.分配a std::aligned_storage来保存Foo数组,调用placement new来构造Foo数组aligned_storage,然后当你想要释放数组时,解除分配aligned_storage不调用placement的删除.
当然这仍然是一个糟糕的设计,可能会导致内存泄漏或其他问题取决于Foo::~Foo()应该做什么,但至少它不是UB.
| 归档时间: |
|
| 查看次数: |
165 次 |
| 最近记录: |