提问人:tongstar 提问时间:5/2/2023 更新时间:5/2/2023 访问量:133
将指针转换为 std::uint64_t 并再次转换回指针时出现内存问题
Memory issues when converting a pointer to std::uint64_t and back to a pointer again
问:
代码如下所示。
struct tNode
{
int data;
tNode* next;
tNode(const int& data, tNode* next = nullptr)
{
this->data = data;
this->next = next;
}
};
int main()
{
tNode* ptr = new tNode(1);
std::uint64_t num_ptr = reinterpret_cast<std::uint64_t>(ptr);
delete ptr;
auto back_to_ptr = reinterpret_cast<tNode*>(num_ptr);
tNode* ret = back_to_ptr->next;
std::cout << ret;
}
当我尝试使用 MSVC 编译器在 Visual Studio 2022 中进行调试时,我无法检测到任何错误。
我相信应该输出有关内存访问冲突的错误信息,那么为什么上面的代码工作正常?tNode* ret = back_to_ptr->next;
我一直在寻找将指针转换为 int 类型的问题。 使用 Visual Studio 2022,我通过获取断点来调试上述示例。
答:
2赞
templatetypedef
5/2/2023
#1
幸运的是,这里的问题与从整数到指针的转换无关,反之亦然。相反,问题在于线不会对自己做任何事情,而是破坏它所指向的对象。对该对象的任何进一步使用,无论如何获取指向该对象的指针,都归类为未定义的行为。这意味着您可能会收到内存错误,也可能不会。在你的例子中,碰巧你不会遇到崩溃或访问冲突,即使你正在做的事情清楚地访问了一个对象的生命周期结束后。delete ptr
ptr
评论
1赞
user4581301
5/2/2023
所有这些都是以效率的名义完成的(或者更确切地说是没有完成的)。这种情况是微不足道的,Mark I 眼球很快就把它挑出来了。在一般情况下,检查以确保指向的对象没有被释放,这是报告错误所必需的,必须到处都吓坏了,这将严重影响性能。C++ 有一个策略,即不让你为没有明确要求的东西付费,所以在大多数情况下,不会进行任何检查,编译器在假设你知道自己在做什么的情况下编写代码。
评论
delete ptr;
告诉系统,“我已经完成了这个,并保证我再也不会看它了。在方便的时候,可以随意发布或重复使用它。A) 你违背了诺言!B) 系统尚未发现释放或重用内存不方便,因此不会引发错误。ptr->next;
uint64_t
int
uint64_t
uintptr_t