调用删除后指针无效
Invalid pointer after a call to delete
我在名为 virtual.cpp
:
的文件中有这个简单的代码
#include <iostream>
class Parent
{
public:
virtual ~Parent(){ std::cout << "Parent Destructor" << std::endl; }
virtual void VirtualFunction()
{
std::cout << "VirtualFunctionInParent" << std::endl;
}
};
class Child: public Parent
{
public:
virtual ~Child() { std::cout << "Child Destructor" << std::endl; }
virtual void VirtualFunction()
{
std::cout << "VirtualFunctionInChild" << std::endl;
}
};
int main()
{
Child child1;
Parent *parent1 = &child1;
delete parent1;
}
编译正确
g++ -Wall --pedantic -o virtual virtual.cpp
但是当我 运行 它时,我得到这个错误:
./virtual
Child Destructor
Parent Destructor
free(): invalid pointer
Annullato (core dump creato)
我想是因为我删除了指针parent1,所以擦除指针指向的内存,即&child1
。
因此,当 child1 超出范围时,Child 析构函数会尝试释放不再存在的内存。
我的问题:
- 我的推理正确吗?
- 如果我的推理是正确的,那么处理这种“超出范围”情况的正确方法是什么?
不要在您未使用 new
分配的对象上调用 delete
。该对象在超出范围时将被删除,因此无需特殊操作即可正确销毁它。
如果您希望对象在范围内开始其生命周期并在范围结束时结束其生命周期,请不要使用 new
和 delete
。正常声明即可。
对要管理其生命周期的对象使用 new
和 delete
。使用 new
分配它们,并在完成后调用 delete
。
I delete the pointer parent1, so this erases the memory to which the pointer point. Is my reasoning correct?
没有。您正在从您的删除 中获取核心转储。
只有从 new
返回的地址可以传递给 delete
。
delete
不会 擦除 内存,因为内存没有“已擦除”状态的概念。
which is the correct way to handle this "going out of scope" situation?
删除 delete
行。没必要。
在范围内创建的任何变量在离开该范围时都会自动管理。
第一件事是您不使用new
或任何其他方式来分配动态 内存。所以没有必要使用 delete
.
要回答您的下一个问题,您必须首先告诉我们为什么要在子地址上创建父指针?
更具体地回答你的问题
- 我的推理正确吗?
您永远不会超出范围,因为您是在 main() 中向当前堆栈帧声明变量。为了将变量声明到堆(超出范围),您必须使用动态内存分配。
Parent * parent1 = new(Child);
delete(parent1);
这段代码所做的是在堆中创建一个子 class,然后创建一个有效指向子 class.
范围的本地 parent1 指针
我在名为 virtual.cpp
:
#include <iostream>
class Parent
{
public:
virtual ~Parent(){ std::cout << "Parent Destructor" << std::endl; }
virtual void VirtualFunction()
{
std::cout << "VirtualFunctionInParent" << std::endl;
}
};
class Child: public Parent
{
public:
virtual ~Child() { std::cout << "Child Destructor" << std::endl; }
virtual void VirtualFunction()
{
std::cout << "VirtualFunctionInChild" << std::endl;
}
};
int main()
{
Child child1;
Parent *parent1 = &child1;
delete parent1;
}
编译正确
g++ -Wall --pedantic -o virtual virtual.cpp
但是当我 运行 它时,我得到这个错误:
./virtual
Child Destructor
Parent Destructor
free(): invalid pointer
Annullato (core dump creato)
我想是因为我删除了指针parent1,所以擦除指针指向的内存,即&child1
。
因此,当 child1 超出范围时,Child 析构函数会尝试释放不再存在的内存。
我的问题:
- 我的推理正确吗?
- 如果我的推理是正确的,那么处理这种“超出范围”情况的正确方法是什么?
不要在您未使用 new
分配的对象上调用 delete
。该对象在超出范围时将被删除,因此无需特殊操作即可正确销毁它。
如果您希望对象在范围内开始其生命周期并在范围结束时结束其生命周期,请不要使用 new
和 delete
。正常声明即可。
对要管理其生命周期的对象使用 new
和 delete
。使用 new
分配它们,并在完成后调用 delete
。
I delete the pointer parent1, so this erases the memory to which the pointer point. Is my reasoning correct?
没有。您正在从您的删除 中获取核心转储。
只有从 new
返回的地址可以传递给 delete
。
delete
不会 擦除 内存,因为内存没有“已擦除”状态的概念。
which is the correct way to handle this "going out of scope" situation?
删除 delete
行。没必要。
在范围内创建的任何变量在离开该范围时都会自动管理。
第一件事是您不使用new
或任何其他方式来分配动态 内存。所以没有必要使用 delete
.
要回答您的下一个问题,您必须首先告诉我们为什么要在子地址上创建父指针?
更具体地回答你的问题
- 我的推理正确吗?
您永远不会超出范围,因为您是在 main() 中向当前堆栈帧声明变量。为了将变量声明到堆(超出范围),您必须使用动态内存分配。
Parent * parent1 = new(Child);
delete(parent1);
这段代码所做的是在堆中创建一个子 class,然后创建一个有效指向子 class.
范围的本地 parent1 指针