c++ - 内存重用和UB

标签 c++

下面的代码会产生UB吗?

#include <iostream>
#include <climits>

struct A
{
    ~A(){ std::cout << "Non-trivial" << std::endl; }
};

int main()
{
    A a;
    new (&a) A; 
}   //UB?

DEMO

标准 N3797::3.8/8 [basic.life]

If a program ends the lifetime of an object of type T with static (3.7.1), thread (3.7.2), or automatic (3.7.3) storage duration and if T has a non-trivial destructor, the program must ensure that an object of the original type occupies that same storage location when the implicit destructor call takes place; otherwise the behavior of the program is undefined.

我认为在 main 函数的离开处没有 UB,因为 &a 指向与它最初分配的类型相同的类型。

最佳答案

[3.8/4] A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.

您的程序是否“依赖于”析构函数产生的副作用?显然:

  • 可观察的程序输出在变化的意义上取决于析构函数是否运行

  • 如果析构函数不运行,cout 缓冲区的状态、位置等将不同,并且

  • 程序终止时剩下的刷新操作可能会有所不同。

您可以合理地说,后面的程序行为/流程取决于析构函数是否运行,这意味着技术上未定义的行为。

不过,我冒昧地说,该标准的目的是警告像不释放锁或递减引用计数器这样的析构函数操作可能会产生令人不快的后果,例如后来的挂起或泄漏,并且实际上在所有实际编译器上您发布的程序将按照您的预期行事。

还值得注意的是,一般来说,如果构造函数抛出并且作用域在该内存位置没有有效对象的情况下展开,这种做法是危险的。

关于c++ - 内存重用和UB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26500905/

相关文章:

c++ - 行中的 token 不起作用失败 c++

c++ - 如何在 C++ Linux 中获得 3g 调制解调器信号强度?

c++ - 在 NSData 中存储 C++ 结构/对象

c++ - 将自定义类添加到 Qt 项目

使用概念具有特定值类型的任何容器的 C++ 迭代器

c++ - 重载运算符>>,将一个参数传递给对象而不是三个

c++ - Arduino 中带有构造函数的对象组合

java - 通过 JNI 将多个参数从 java 传递到 c++ 应用程序

c++ - 如何在不丢失顺序的情况下将 std::vector 转换为 std::set

将未初始化的局部变量传递给函数时出现 C++ 编译器警告(?)