在以前删除内存时删除它 我有一个小的C++程序,在那里我创建了一个类的对象。此类的数据有char*m_szFirstName和char*m_szLastName

在以前删除内存时删除它 我有一个小的C++程序,在那里我创建了一个类的对象。此类的数据有char*m_szFirstName和char*m_szLastName,c++,pointers,memory-management,delete-operator,C++,Pointers,Memory Management,Delete Operator,然后将一个对象指定给另一个对象,使两个对象的数据成员指向同一位置。 在析构函数中,我删除为第一个对象分配的内存,并为指针分配空值。像这样的 if (m_szFirstName!= NULL) { delete [] m_szFirstName; m_szFirstName = NULL; } 然后,当我为第二个对象删除内存时,NULL检查不起作用,当我删除内存时,我会崩溃。从调试器中,它显示我的指针不是空的。它有一只脚 我知道以前已经删除了内存,不应该删除。但是,我不知道如何检

然后将一个对象指定给另一个对象,使两个对象的数据成员指向同一位置。 在析构函数中,我删除为第一个对象分配的内存,并为指针分配空值。像这样的

if (m_szFirstName!= NULL)
{
    delete [] m_szFirstName;
    m_szFirstName = NULL;
}
然后,当我为第二个对象删除内存时,NULL检查不起作用,当我删除内存时,我会崩溃。从调试器中,它显示我的指针不是空的。它有一只脚

我知道以前已经删除了内存,不应该删除。但是,我不知道如何检查是否应该删除内存。

崩溃原因: 您应该遵循以避免指针悬空的问题

如果需要自己显式声明析构函数、复制构造函数或复制赋值运算符,则可能需要显式声明这三个运算符

在您的情况下,您不定义复制赋值运算符,从而导致指针的浅复制

建议的解决办法:

如果您可以使用std::string而不是char*,只需简单地使用std::string,它就比任何愚蠢的指针都具有首要的优先权。 通过使用std::string,可以避免所有时髦的指针

如果您无法继续阅读,则以下建议一般适用于任何类指针成员

请注意,这里的理想解决方案是根本不使用原始指针,每当您使用原始指针时,您都会被迫手动管理它们获取的资源,手动管理资源总是很困难且容易出错。因此,我们有责任避免这种情况

为此,应使用隐式管理指针动态内存的。使用智能指针将确保动态内存在使用后隐式释放&您不必手动管理它

您所处的场景是C++中依赖于手动资源管理的原因,使用智能指针是您的方法。

警告: 请注意,我限制自己建议使用哪个智能指针,因为选择取决于所涉及元素的所有权和寿命,这在问题中提供的数据中并不清楚。因此我建议阅读


选择要使用的智能指针。

如果m_szFirstName==m_szLastName,请不要再次删除它。 但是,当您将一个指针分配给另一个指针时,这将导致内存泄漏。

if (m_szFirstName!= NULL)
{ 
  delete [] m_szFirstName;
  m_szFirstName = NULL;
}
您只将m_szFirstName设置为指向NULL,而不是m_szLastName。这意味着您必须有某种方法来跟踪它们指向同一位置的事实。他们指向同一地点有什么原因吗?你能复制这个名字而不是把指针指向同一个地方吗


如果您需要两个指针来共享相同的数据,我会看看std::tr1::shared_ptr,这将通过跟踪引用数量并在引用数量达到0时删除来为您解决此问题。

将第一个指针分配给第二个指针后,如果有两个指针指向同一位置,则有两个指针指向同一地址。删除其中一个将释放它们指向的内存。但是将一个指针设置为NULL不会改变另一个指针。例如,如果有两个整数,也会发生同样的情况

int a = 3;
int b = a;
现在如果你跑

a = 0;

b的值不变。同样,当您更改第一个指针时,第二个指针不会更改,但当您更改任一指针指向的内存时,您也可以通过另一个指针看到效果。

您的问题是一个典型的C/C++问题,称为悬空指针问题。取消对悬挂指针的引用导致崩溃。问题在于引用计数。将相同的内存分配给第二个指针后,引用计数应为2。所以,若删除一个指针引用,则计数应为1,并且除非计数为0,否则不应释放或释放内存。在0时,可以对其进行垃圾收集


现在上面有很好的答案来解决你的问题。因为您使用C++,所以您可以使用AutoMyPTR或SyrdY-PTR之类的东西。它们提供了我上面提到的引用计数功能,即使您不必担心删除或释放对象,这些类也会很小心。它们工作于一种被称为RAII模式的模拟,当堆栈上的对象超出范围时,析构函数会自动神奇地调用。

删除对象后,只需停止将指针设置为NULL即可。正如你所见,这只会导致疼痛。由于指针不为NULL,因此不能假定它尚未被删除

您可以使用任何您想要的合理模式
避免这个问题。例如,Boost的shared_ptr是一个不错的选择。

你能展示一些代码吗?当你复制Person实例时,第二个对象有它自己的成员。也就是说,它有自己的m_szFirstName,其值是从原始实例复制的。请注意,仅复制指针,而不复制指向的内存。因此,当删除第一个实例后将其设置为NULL时,第二个实例保留其值并指向已删除的内存。代码太大,无法在此处附加。我想演示一下,除非使用赋值运算符并在其中进行复制,否则无法将一个具有char*数据的对象分配给另一个对象。否则,两个对象的数据将指向相同的内存。当删除第一个对象时,第二个对象数据将有损坏的数据。注意:当使用RAII时,您仍然应该遵循[两大法则]这一正确答案。然而,在他的例子中,他很可能真正需要的是一个std::字符串来存储它的名字和姓氏。@ereOn:很可能是的,当然我们不知道,无论如何,这个答案对于任何指针成员都是适用的。当然,如果可以使用std::string,那么它比任何一种愚蠢的指针都有优先权。我看到很多与Q有关的作业都在寻求不使用std::string的解决方案,这有点傻,我假设这是其中一种情况。无论如何,我会编辑答案来反映这一点。谢谢。@Als:你完全正确:在这一点上,我们只能猜测。非常好而且完整的答案:这是我的+1。谢谢你的建议。我要寻找的是如何在删除之前判断指针是否有效。如果我删除一个ponter,给它赋一个空值,然后再次删除,它应该不会崩溃。此外,第二次检查NULL失败,因为指针已被删除,并且不再是有效指针。删除指针后,将指针设置为nullptr或NULL是正确的做法,这样,如果再次删除同一指针,则不会发生任何事情。就我而言,由于一些愚蠢的原因,它崩溃了。无论如何,谢谢你的建议。@SaleemYusuf如果你再次删除同一个指针,它不会阻止你造成崩溃,正如你所看到的。它所做的只是让您认为,如果指针变量包含非NULL的值,则意味着可以安全地访问它,但事实并非如此。所以这是一个非常坏的习惯。与其将指针设置为NULL,不如不要访问它。或者,最好使用一个合理的指针类。