删除之前删除的内存

发布于 2025-01-06 20:46:28 字数 498 浏览 1 评论 0原文

我有一个小型 C++ 程序,在其中创建 Person 类的两个对象。该类具有用于数据的 char *m_szFirstNamechar *m_szLastName

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

if (m_szFirstName!= NULL)
{
    delete [] m_szFirstName;
    m_szFirstName = NULL;
}

然后,当我去删除第二个对象的内存时,对 NULL 的检查不起作用,当我删除内存时,我会崩溃。从调试器中,它显示我的指针不是NULL。它有 0xfeee

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

I have a small C++ program where I create two objects of a Person class. This class has char *m_szFirstName and char *m_szLastName for data.

I then I assign one object to another, causing both object's data members to point to same location.
In the destructor, I delete what memory I had allocated for the first object and assign NULL values to the pointers. Something like this.

if (m_szFirstName!= NULL)
{
    delete [] m_szFirstName;
    m_szFirstName = NULL;
}

Then when I go to delete memory for the second object, the check for NULL does not work and when I delete memory, I get a crash. From debugger, it show that my pointer is not NULL. It has 0xfeee.

I am aware that memory was already deleted before and should not be delete. However, I don't know how to check whether I should delete memory or not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

给我一枪 2025-01-13 20:46:28

崩溃原因:
您应该遵循三法则以避免这个悬空指针的问题。

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

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

建议的解决方案:

如果您可以使用 std::string 而不是 char *,只需使用 std::string ,它比任何愚蠢的指针东西都有首要的偏好。
您可以使用 std::string 来避免所有时髦的指针问题。

如果您无法继续阅读,并且以下建议通常适用于任何类指针成员。

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

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

您所遇到的情况正是在 C++ 中您应该依赖 RAII< /strong> 而不是手动资源管理&对于您的情况,可以使用智能指针。

警告:
请注意,我没有建议使用哪个智能指针,因为选择取决于所涉及元素的所有权生命周期,即问题中提供的数据不清楚。所以我建议阅读

我使用哪种指针何时?

来选择要使用的智能指针。

Reason for Crash:
You should follow the Rule of Three to avoid this problem of dangling pointers.

If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.

In your case You do not define a copy assignment operator thus leading to shallow copy of the pointer.

Suggested Solution:

If you can use std::string instead of char * just simply use std::string, it has the first and foremost preference over any kind of silly pointer stuff.
You can avoid all the funky pointer stuff by using std::string.

If you can't read on and the following suggestion applies to any class pointer member in general.

Note that the ideal solution here is to not use raw pointers at all, Whenever you use raw pointers you are forced to manually manage the resources acquired by them, it is always difficult and error prone to manually manage resources.So the onus is to avoid it.

To do so, You should use a Smart pointer which will manage the dynamic memory of the pointer implicitly.Using a smart pointer will ensure that the dynamic memory is implicitly released after usage & you do not have to manually manage it.

The scenario you have is the very reason that in C++ you should rely on RAII rather than manual resource management & using a Smart pointer is the way to go about in your case.

Caveat:
Note that I restrained myself from suggesting which smart pointer to use because the choice rather depends on the ownership and lifetime of the elements involved, which is not clear from the data provided in the Question.So I will suggest reading,

Which kind of pointer do I use when?

to make your choice of the smart pointer to use.

和我恋爱吧 2025-01-13 20:46:28

if (m_szFirstName!= NULL)
{ 
  delete [] m_szFirstName;
  m_szFirstName = NULL;
}

只需将 m_szFirstName 设置为指向 NULL,而不是 m_szLastName。这意味着您必须有某种方法来跟踪它们指向同一位置的事实。他们指向同一个位置有原因吗?你能复制这个名字而不是把指针指向同一个地方吗?

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

With

if (m_szFirstName!= NULL)
{ 
  delete [] m_szFirstName;
  m_szFirstName = NULL;
}

You only set m_szFirstName to point to NULL, not m_szLastName. This means you have to have some way to keep track of the fact they point to the same location. Is there a reason they point to the same location? Could you copy the name instead of pointing the pointers to the same place?

If you need the two pointers to shared the same data, I would have a look at std::tr1::shared_ptr, which will solve this issue for you by keeping track of the number of references and deleting when the number of references reaches 0.

南烟 2025-01-13 20:46:28

如果 (m_szFirstName == m_szLastName),请不要再次删除它。
但这会给你带来内存泄漏(当你将一个指针分配给另一个指针时)。

Don't delete it again, if (m_szFirstName == m_szLastName).
But this will give you a memory leak (when you assign one pointer to other).

茶花眉 2025-01-13 20:46:28

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

int a = 3;
int b = a;

现在,如果您运行

a = 0;

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

When you have two pointers pointing to the same location (after you assigned the first one to the second one), you have two pointers pointing at the same address. Deleting one frees the memory pointed to by both of them. But setting one to NULL doesn't alter the other pointer. The same happens if you have two integers, for example.

int a = 3;
int b = a;

Now if you run

a = 0;

the value of b doesn't change. The same way your second pointer doesn't change when you alter the first one (but when you alter the memory pointed to by either pointer, you can see the effect through the other as well).

时光暖心i 2025-01-13 20:46:28

您的问题是一个经典的 C/C++ 问题,称为“悬空指针”问题。取消引用悬空指针导致了崩溃。问题在于引用计数。一旦你将相同的内存分配给第二个指针,那么引用计数应该是2。因此,如果你删除一个指针,引用计数应该变成1,并且除非计数为0,否则你的内存不应该被释放或释放。在0时,它可以被垃圾收集。

现在上面有很好的答案可以解决您的问题。由于您使用的是 C++,因此您可以使用 auto_ptr(或共享指针)之类的东西。它们提供了我上面提到的,引用计数的东西,甚至你不需要担心删除或释放你的对象,这些类会照顾。他们致力于 RAII 模式,当堆栈上的对象超出范围时,会自动神奇地调用析构函数。

Your problem is a classic C/C++ problem which is known as "Dangling Pointer" problem. Dereferencing the dangling pointer has resulted in the crash. The problem is about reference counting. Once you assign the same memory to the second pointer then the reference count should be 2. So if you delete one pointer reference count should become 1 and your memory should not be deallocated or freed unless count is 0. At 0 it can be garbage collected.

Now there are good answers above to solve your problem. Since you are using C++ so you can use something like an auto_ptr (OR shared_ptr). They provide what I had mentioned above, the reference counting stuff and even you need not worry about deleting or freeing your objects, these classes would take care. They work on simething known as RAII pattern where a destructor is auto-magically called when the object on the stack goes out of scope.

送你一个梦 2025-01-13 20:46:28

删除对象后,只需停止将指针设置为 NULL 即可。正如你所看到的,它只会导致痛苦。您不能假设因为指针不为 NULL,所以它尚未被删除。

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

Just stop setting pointers to NULL when you have deleted the object. As you can see, it just leads to pain. You cannot assume that because the pointer is not-NULL, it has not been deleted already.

You can use any sensible pattern you want to avoid this problem. For example, Boost's shared_ptr is a great choice.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文