使用已删除的指针地址.据我所知,

Use of a deleted pointer address

本文关键字:地址 据我所知 指针 删除      更新时间:2023-10-16

(*(据我所知,该标准允许实现来修改delete操作员的操作数,但是大多数实现都不会这样做。

int* ptr = new int(0);
delete ptr; //delete is allowed to modify ptr, for example set it to 0
std::cout << ptr; // UB?

确认(*(,读取ptr(以打印它的形式(是否定义明确?

如果delete修改了ptr,是否允许设置陷阱值,这将使读取ptr UB?

在C 中14这是实现定义的行为,[basic.stc.dynamic.deallocation]/4:

如果标准库中给出的交易函数的参数是一个指针,而不是零指针值,则DealLocation函数应处理指针引用的存储空间,使所有指向交易量存储的任何部分的指针无效。

通过无效的指针值并将无效的指针值传递给DealLocation函数的间接行为具有不确定的行为。无效的指针值的任何其他用途都具有实现定义的行为

有一个脚注:

某些实现可能定义复制无效的指针值会导致系统生成的运行时故障。

这发生了变化,因为C 11,大胆的文本说"不确定的行为",并且没有脚注。


为了回答您的问题,允许delete ptr;设置陷阱值,该值将导致std::cout << ptr的运行时故障。编译器文档必须指定行为。这是一个比UB狭窄的限制,在这种情况下,任何不稳定的行为都是可以允许的。

在此示例中,默认情况下, std::cout << ptr并不是未定义的行为,因为 ptr根本没有被删除,因此实际上设置了什么值。

默认情况下,STL不能为int*指针定义operator<<。它定义:

  • operator<<的CC_12,用于打印零终止文本。

  • void*的通用operator<<,它只需打印指针所设置的内存地址本身,而不是指向的数据。

由于int*隐式转换为void*,因此调用std::cin << ptr实际上是在调用operator<<(std::cin, (void*)ptr),因此打印了ptr保留的内存地址。

只有当您的应用程序定义了自己的operator<<int*,然后在删除指针后尝试将其解释。