C++ 如何检测指针是否被删除并安全删除它?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15730827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to detect if a pointer was deleted and securely delete it?
提问by ahmedsafan86
In C++How to decide or know if a pointer was deleted before??
在C++ 中如何决定或知道之前是否删除了一个指针??
when i tried to delete a pointer that was previously deleted in another part of the code it threw an exception that can't be handled.
当我试图删除之前在另一部分代码中删除的指针时,它抛出了一个无法处理的异常。
I was wondering if there is a way to check or try delete the pointer ? any reference about advanced memory operations.
我想知道是否有办法检查或尝试删除指针?有关高级内存操作的任何参考。
also i want to master the un-handled exceptions of pointers and the access to protected or access is violation ,... this kind of error.
我还想掌握指针的未处理异常以及对受保护或访问的访问是违规的,...这种错误。
thanks for those who give some of their knowledge and their time to help other people and share their benfits
感谢那些提供一些知识和时间来帮助他人并分享他们的好处的人
Update
更新
The big advice from a lot of modern c++ developers community is - Use smart pointers or try to avoid the use of raw pointers. But for throw security and insuring free of memory (ISO_CPP_FAQ) and of course if you want to avoid the small overhead of using smart pointers[may not be noticeable always but they have overhead] you can write your custom methods that deal with raw pointers [type*] - this is not general. Prefer always smart pointers to raw pointers.
许多现代 C++ 开发人员社区的重要建议是 - 使用智能指针或尽量避免使用原始指针。但是为了抛出安全性并确保没有内存(ISO_CPP_FAQ),当然,如果您想避免使用智能指针的小开销[可能并不总是很明显,但它们有开销],您可以编写处理原始指针的自定义方法[ type*] - 这不是一般的。 总是喜欢智能指针而不是原始指针。
In 'Going Native 2013' a common advice given was - Never use raw pointers.
在“Going Native 2013”中,给出的一个常见建议是——永远不要使用原始指针。
回答by Alok Save
There can be three solutions. You might want to choose one depending on the effort/quality ratio you want to acheive:
可以有三种解决方案。您可能希望根据要实现的工作量/质量比选择一个:
Elegant and most correct solution:
优雅和最正确的解决方案:
Use smart pointersand you do not have to manually call delete
ever again. This is the best possible way to overcome this problem. It utilizes the principle of RAII which works perfectly for a language like C++ which does not have an in-built garbage collector.
使用智能指针,您不必delete
再次手动调用。这是克服这个问题的最好方法。它利用了 RAII 的原理,该原理非常适合像 C++ 这样没有内置垃圾收集器的语言。
Less elegant but workable solution:
不太优雅但可行的解决方案:
Assign the pointer to NULL
after deletion. Calling delete
on a NULL
pointer is a no-op so it removes the need to have that extra NULL
check but this might hidesome problems instead of making them visible.
NULL
删除后分配指针。调用delete
一个NULL
指针是一个空操作,因此就不再需要有额外的NULL
检查,但是这可能会掩盖一些问题,而不是使他们看到的。
Less elegant but more correct solution:
不太优雅但更正确的解决方案:
Hunt down all the multiple delete
problems by letting your program crash. You might as well use memory analyzer programs like valgrind and then fix your code to avoid all these problems.
delete
通过让程序崩溃来解决所有多重问题。您不妨使用 valgrind 之类的内存分析器程序,然后修复您的代码以避免所有这些问题。
回答by Ben Zotto
This is a good question, but one of the fundamental truths of working in a manually memory managed environment (like C/C++ and its cousins) is that there's no good way of looking at a pointer after the factand asking whether it's valid-- once it's become invalid, it's gone, and looking at it is prone to blowing up. Your job is to make sure that it's never deleted or freed more than once, and never accessed after that time.
这是一个好问题,但在手动内存管理环境(如 C/C++ 及其表亲)中工作的基本事实之一是,没有什么好方法可以事后查看指针并询问它是否有效——一旦失效,它就消失了,看着它容易炸毁。你的工作是确保它永远不会被删除或释放超过一次,并且在那之后永远不会被访问。
Definitely look at the smart pointers, which were invented to make programmer's lives easier in just these circumstances. (The more traditional method is to be careful, not screw it up, and then maybe assign NULL to the pointer when you know it's been deleted, as Alok says.)
一定要看看智能指针,它的发明是为了在这些情况下使程序员的生活更轻松。(更传统的方法是小心,不要搞砸,然后当您知道它已被删除时,可能会将 NULL 分配给指针,正如 Alok 所说。)
回答by Alexey Frunze
In C++ How to decide or know if a pointer was deleted before??
在 C++ 中如何决定或知道之前是否删除了一个指针??
The language standard does not offer any legal way to determine whether an arbitrary pointer is valid or not.
语言标准没有提供任何合法的方法来确定任意指针是否有效。
There's one way, but it's highly compiler/OS-specific. You can either hook into the existing memory manager or replace it with your own and provide a dedicated function for pointer validation. It may be not very easy to do, though. And you don't really want to rely on this functionality if performance is critical.
有一种方法,但它是高度特定于编译器/操作系统的。您可以连接到现有的内存管理器或将其替换为您自己的,并提供用于指针验证的专用函数。不过,这可能并不容易。如果性能至关重要,您真的不想依赖此功能。
回答by James Kanze
The pointer won't tell you anything. Your design should: if you're using dynamic allocation, it's normally becauseyour application requires the object to have a specific lifetime, so you know when to correctly delete the object. If the object is copyable, or has a lifetime which corresponds to scope, you don't (normally) allocate it dynamically.
指针不会告诉你任何事情。您的设计应该:如果您使用动态分配,通常是因为您的应用程序要求对象具有特定的生命周期,因此您知道何时正确删除对象。如果对象是可复制的,或者具有对应于作用域的生命周期,则您(通常)不会动态分配它。
There are, of course, exceptions in very low level code—if
you're implementing something like std::vector
, you will have
to use some sort of dynamic allocation, because the size isn't
known at compile time. But such allocations shouldn't escape;
it's the responsibility of the low level class to handle the
memory.
当然,在非常低级的代码中也有例外——如果你正在实现类似的东西std::vector
,你将不得不使用某种动态分配,因为在编译时不知道大小。但是这样的分配不应该逃避;处理内存是低级类的责任。
Finally, buffer overruns, accessing already deleted memory, and
the like are undefined behavior. They do not, in general,
result in an exception, and there's not a generic way of
handling them. (You canusually arrange to get a signal when
such things occur, but there are so few things you can do from a
signal handler, this doesn't really help much.) In general,
what you want is for the program to crash, since you don't know
what state it is in. In the rare cases where this is not the
case, you have to fall back on implementation defined
extensions, if they exist. If you compile with the /EHa
option with VC++, for example, what would normally be a crash
will be coverted into a C++ exception. But that's a VC++
extension, and you still don't know the overall state of the
program when this occurs. If it's because you've corrupted the
free space arena, there's probably not much you can do even if
you catch the exception (and there's a good chance you'll get
another exception from a destructor trying to free memory when
you unwind the stack).
最后,缓冲区溢出、访问已删除的内存等都是未定义的行为。通常,它们不会导致异常,并且没有处理它们的通用方法。(您通常可以安排在发生此类事情时获取信号,但是您可以从信号处理程序中执行的操作很少,这并没有多大帮助。)通常,您想要的是程序崩溃,因为你不知道它处于什么状态。在极少数情况下不是这种情况,你必须依靠实现定义的扩展,如果它们存在的话。如果你编译/EHa
例如,使用 VC++ 选项,通常会发生崩溃的情况将被转换为 C++ 异常。但那是 VC++ 的扩展,发生这种情况时,您仍然不知道程序的整体状态。如果是因为您破坏了可用空间领域,那么即使您捕捉到异常,您也可能无能为力(并且很有可能在您展开堆栈时尝试释放内存的析构函数会得到另一个异常) .
回答by 4pie0
use shared_ptr<>
and shared_array<>
, remember shared_ptr<>
can be used to manage memory allocated to an array only if appropriate Deleter is provided, otherwise use shared_array<>
to manage your arrays
使用shared_ptr<>
and shared_array<>
,记住shared_ptr<>
只有在提供了适当的 Deleter 时才能用于管理分配给数组的内存,否则用于shared_array<>
管理您的数组
A* a_tab=new A[100];
boost::shared_ptr<A> a_tab_ok(a_tab,ArrayDeleter<A>());
//only ok if
//只有当
template <typename T>
class ArrayDeleter
{
public:
void operator () (T* d) const
{
delete [] d; //will delete array!
}
};
is provided
提供
回答by Saqlain
Smart pointer are better choice to avoid such problems (but you must have complete understanding before using them also), but I would like to mention performance limitations associated with Smart pointers, reason is they usually use atomic operations for example InterlockedIncrement in Win32 API for reference counting. These functions are significantly slower than plain integer arithmetic. I am not sure such little performance penalty acceptable in your case or not.
智能指针是避免此类问题的更好选择(但您也必须在使用它们之前完全了解它们),但我想提一下与智能指针相关的性能限制,原因是它们通常使用原子操作,例如 Win32 API 中的 InterlockedIncrement 以供参考数数。这些函数比普通的整数运算要慢得多。我不确定您的情况是否可以接受这么小的性能损失。
What i usually do is (so i don't have to spend days later on to debug nasty bugs), i spend lot of time on design, and object lifetime, before moving for actual coding, as i delete memory I specifically set pointer to NULL, it is good practice as far as i think. Again perhaps the real solution is to spend more time on determining dependencies and object life time before moving on!
我通常做的是(所以我不必在几天后调试讨厌的错误),在移动进行实际编码之前,我花了很多时间在设计和对象生命周期上,因为我删除了我专门设置的内存指针NULL,据我所知,这是一种很好的做法。也许真正的解决方案是在继续之前花更多时间确定依赖项和对象生命周期!
回答by Martin Fehrs
I know this thread is old. But if someone else is reading this, he should know about unique_ptr. shared_ptr has indeed an overhead. The counter is stored on the heap. Every time the counter is accessed, there is a risk of a processor cache mismatch. unique_ptr Is more limited but has no overhead in comparison to plain pointers. My suggestion is to prefer unique_ptr over shared_ptr when you do not need reference counting. Another important notice is, that unique_ptr works well with arrays. If i remember correctly this is also true for shared_ptr since C++17.
我知道这个线程是旧的。但是如果其他人正在阅读本文,他应该知道unique_ptr。shared_ptr 确实有开销。计数器存储在堆上。每次访问计数器时,都存在处理器缓存不匹配的风险。unique_ptr 与普通指针相比更有限,但没有开销。我的建议是,当您不需要引用计数时,更喜欢 unique_ptr 而不是 shared_ptr。另一个重要的注意事项是,unique_ptr 适用于数组。如果我没记错的话,自 C++17 以来,shared_ptr 也是如此。