简体   繁体   English

内存泄漏问题; 删除指针

[英]Memory leak issue; deleting a pointer

If I have a pointer pointing to a specific memory address at the heap. 如果我有一个指针指向堆上的特定内存地址。 I would like this same pointer to point to another memory address, should I first delete the pointer? 我想这个相同的指针指向另一个内存地址,我应该先delete指针? But, in this case am I actually deleting the pointer or just breaking the reference (memory address) the pointer is pointing at? 但是,在这种情况下,我实际上是删除指针还是只是破坏指针指向的引用(内存地址)?

So, in other words, if I delete a pointer, does this mean it doesn't exist any more? 所以,换句话说,如果我delete一个指针,这是否意味着它不再存在? Or, it is there, but not pointing to where it was? 或者,它在那里,但没有指出它在哪里?

The syntax of delete is a bit misleading. delete的语法有点误导。 When you write 当你写作

T* ptr = /* ... */
delete ptr;

You are not deleting the variable ptr . 没有删除变量ptr Instead, you are deleting the object that ptr points at. 相反,您正在删除ptr指向的对象。 The value of ptr is unchanged and it still points where it used to, so you should be sure not to dereference it without first reassigning it. ptr的值没有变化,它仍然指向以前的位置,所以你应该确保在没有重新分配它的情况下不要取消引用它。

There is no requirement that you delete a pointer before you reassign it. 在重新分配之前,不要求delete指针。 However, you should ensure that if you are about to reassign a pointer in a way that causes you to lose your last reference to the object being pointed at (for example, if this pointer is the only pointer in the program to its pointee), then you should delete it to ensure that you don't leak memory. 但是,如果要以一种导致丢失对指向对象的最后一个引用的方式重新分配指针,则应该确保(例如,如果此指针是程序中指向其指针的唯一指针),然后你应该delete它,以确保你不泄漏内存。

One technique many C++ programmers use to simplify the logic for when to free memory is to use smart pointers , objects that overload the operators necessary to mimic a pointer and that have custom code that executes automatically to help keep track of resources. 许多C ++程序员用来简化何时释放内存的逻辑的一种技术是使用智能指针 ,重载模拟指针所需的运算符的对象以及具有自动执行的自定义代码以帮助跟踪资源的对象。 The new C++0x standard, for example, will provide a shared_ptr and unique_ptr type for this purpose. 例如,新的C ++ 0x标准将为此提供shared_ptrunique_ptr类型。 shared_ptr acts like a regular pointer, except that it keeps track of how many shared_ptr s there are to a resource. shared_ptr就像一个常规指针,除了它跟踪资源有多少shared_ptr When the last shared_ptr to a resource changes where it's pointing (either by being reassigned or by being destroyed), it then frees the resource. 当资源的最后一个shared_ptr改变它所指向的位置时(通过重新分配或被销毁),它随后释放资源。 For example: 例如:

{
    shared_ptr<int> myPtr(new int);
    *myPtr = 137;
    {
       shared_ptr<int> myOtherPtr = myPtr;
       *myPtr = 42;
    }
}

Notice that nowhere in this code is there a call to delete to match the call to new ! 请注意,此代码中没有任何地方调用delete来匹配对new的调用! This is because the shared_ptr is smart enough to notice when the last pointer stops pointing to the resource. 这是因为shared_ptr足够智能,可以在最后一个指针停止指向资源时注意到。

There are a few idiosyncrasies to be aware of when using smart pointers, but they're well worth the time investment to learn about. 使用智能指针时需要注意一些特性,但它们值得花时间投资来学习。 You can write much cleaner code once you understand how they work. 一旦了解了它们的工作原理,就可以编写更清晰的代码。

When you delete a pointer you release the memory allocated to the pointed to object. delete指针时, 释放分配给指向对象的内存。 So if you just want your pointer to point to a new memory location you should not delete the pointer. 所以,如果你只是想你的指针指向一个新的存储位置,你应该delete的指针。 But if you want to destroy the object currently it is pointing to and then then point to a different object then you should delete the pointer. 但是如果你想要销毁它指向的对象,然后指向另一个对象,那么你应该delete指针。

xtofl, while being funny, is a bit correct. xtofl,虽然有趣,但有点正确。

If YOU 'new' a memory address, then you should delete it, otherwise leave it alone. 如果你'新'是一个内存地址,那么你应该删除它,否则不管它。 Maybe you are thinking too much about it, but you think about it like this. 也许你正在考虑太多,但你想到这样。 Yea, the memory is always there, but if you put a fence around it, you need to take the fence down, or no one else can you it. 是的,记忆总是在那里,但是如果你在它周围放一个栅栏,你需要把栅栏放下来,或者没有其他人可以。

When you call delete you mark the memory pointed to by the pointer as free - the heap takes ownership of it and can reuse it, that's all, the pointer itself is usually unchanged . 当你调用delete你将指针指向的内存标记为空闲 - 堆获取它的所有权并可以重用它,就是这样, 指针本身通常不变

What to do with the pointer depends on what you want. 如何处理指针取决于你想要什么。 If you no longer need that memory block - use delete to free the block. 如果您不再需要该内存块 - 请使用delete来释放该块。 If you need it later - store the address somewhere where you can retrieve it later. 如果您以后需要它 - 将地址存储在稍后可以检索它的地方。

In short, you do not "delete a pointer", you delete whatever the pointer points to. 简而言之,您不“删除指针”,删除指针指向的任何内容。

This is a classical problem: If you delete it, and someone else is pointing to it, they will read garbage (and most likely crash your application). 这是一个经典问题:如果删除它,而其他人指向它,它们将读取垃圾(并且很可能会使应用程序崩溃)。 On the other hand, if you do not and this was the last pointer, your application will leak memory. 另一方面,如果你不这样,这是最后一个指针,你的应用程序将泄漏内存。

In addition, a pointer may point to thing that were not originally allocated by "new", eg a static variable, an object on the stack, or into the middle of another object. 另外,指针可以指向最初未由“new”分配的事物,例如静态变量,堆栈上的对象或另一个对象的中间。 In all those cases you're not allowed to delete whatever the pointer points to. 在所有这些情况下,您不能删除指针指向的任何内容。

Typically, when designing an application, you (yes, you) have to decide which part of the application owns a specific object. 通常,在设计应用程序时,您(是的,您)必须决定应用程序的哪个部分拥有特定对象。 It, and only it, should delete the objects when it is done with it. 只有它,它应该在完成对象时删除它们。

To answer your question directly, this has been asked before. 要直接回答您的问题,之前已经提出过这个问题。 delete will delete what your pointer points to, but there was a suggestion by Bjarne Stroustrup that the value of the pointer itself can no longer be relied upon, particularly if it is an l-value. delete将删除指针指向的内容,但Bjarne Stroustrup建议不再依赖指针本身的值,特别是如果它是l值。 However that does not affect the ability to reassign it so this would be valid: 但是,这不会影响重新分配它的能力,因此这将是有效的:

for( p = first; p != last; ++p )
{
   delete p;
}

if you are iterating over an array of pointers, all of which had been allocated with new . 如果你正在迭代一个指针数组,所有指针都已经分配了new

Memory management in C++ is best done with a technique called RAII, "resource acquisition is initialization". C ++中的内存管理最好使用称为RAII的技术,“资源获取是初始化”。

What that actually means is that at the time you allocate the resource you immediately take care of its lifetime, ie you "manage" it by putting it inside some object that will delete it for you when it's no longer required. 这实际上意味着,在您分配资源时,您会立即处理它的生命周期,即您通过将其置于某个对象中来“管理”它,当它不再需要时将为您删除它。

shared_ptr is a technique commonly used where the resource will be used in many places and you do not know for certain which will be the last one to "release" it, ie no longer require it. shared_ptr是一种常用的技术,资源将在许多地方使用,你不确定哪个是最后一个“释放”它,即不再需要它。

shared_ptr is often used in other places simply for its semantics, ie you can copy and assign them easily enough. shared_ptr通常仅在其他地方用于其语义,即您可以轻松地复制和分配它们。

There are other memory management smart pointers, in particular std::auto_ptr which will be superceded by unique_ptr, and there is also scoped_ptr. 还有其他内存管理智能指针,特别是std :: auto_ptr,它将被unique_ptr取代,并且还有scoped_ptr。 weak_ptr is a methodology to be able to obtain a shared_ptr if one exists somewhere, but not holding a reference yourself. weak_ptr是一种能够获得shared_ptr的方法,如果一个存在于某个地方,但不能自己持有一个引用。 You call "lock()" which gives you a shared_ptr to memory or a NULL one if all the current shared pointers have gone. 你调用“lock()”,它给你一个shared_ptr到内存或一个NULL,如果所有当前的共享指针已经消失。

For arrays, you would not normally use a smart pointer but simply use vector. 对于数组,您通常不会使用智能指针,只需使用向量。

For strings you would normally use the string class rather than think of it as a vector of char. 对于字符串,通常使用字符串类而不是将其视为char的向量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM