代码之家  ›  专栏  ›  技术社区  ›  ahmedsafan86

如何检测指针是否被删除并安全删除?

  •  35
  • ahmedsafan86  · 技术社区  · 12 年前

    在里面 C++ 如何决定或知道指针之前是否被删除??

    当我试图删除之前在代码的另一部分中删除的指针时,它引发了一个无法处理的异常。

    我想知道是否有办法检查或尝试删除指针?关于高级内存操作的任何参考。

    此外,我还想掌握指针的未处理异常,以及对受保护或访问是违规的,。。。这种错误。

    感谢那些贡献自己的知识和时间来帮助他人并分享他们的智慧的人


    使现代化

    来自许多现代c++开发人员社区的重要建议是——使用智能指针或尽量避免使用原始指针。但对于投掷安全性和确保内存空闲( ISO_CPP_FAQ )当然,如果你想避免使用智能指针的小开销[可能并不总是显而易见,但它们有开销],你可以编写处理原始指针的自定义方法[type*]-这不是一般性的。 总是喜欢智能指针而不是原始指针 .

    在《Going Native 2013》中,一个常见的建议是——永远不要使用原始指针。

    7 回复  |  直到 9 年前
        1
  •  36
  •   Community CDub    8 年前

    可以有三种解决方案。你可能想根据你想要达到的努力/质量比来选择一个:

    优雅且最正确的解决方案:

    使用 smart pointers 并且您不必手动呼叫 delete 再次。这是克服这个问题的最好办法。它利用了RAII的原理,该原理非常适用于像C++这样没有内置垃圾收集器的语言。

    不那么优雅但可行的解决方案:

    将指针分配给 NULL 删除后。使命感 删去 无效的 指针是一个无操作指针,因此它不需要额外的指针 无效的 检查,但这可能 隐藏 一些问题,而不是让它们可见。

    不那么优雅但更正确的解决方案:

    找出所有倍数 删去 让程序崩溃带来的问题。您还可以使用像valgrind这样的内存分析器程序,然后修复代码以避免所有这些问题。

        2
  •  6
  •   Ben Zotto sberry    12 年前

    这是一个很好的问题,但在手动内存管理环境(如C/C++及其同类环境)中工作的一个基本事实是,没有很好的方法来查看指针 事后 问它是否有效——一旦它变得无效,它就消失了,看着它很容易爆炸。你的工作是确保它永远不会被删除或释放一次以上,并且在那之后永远不会被访问。

    一定要看看智能指针,它们是为了在这种情况下让程序员的生活更轻松而发明的。(正如Alok所说,更传统的方法是小心,不要把它搞砸,然后当你知道指针被删除时,可能会给它赋值NULL。)

        3
  •  4
  •   Alexey Frunze    12 年前

    在C++中,如何决定或知道指针之前是否被删除??

    语言标准没有提供任何合法的方法来确定任意指针是否有效。

    有一种方法,但它是高度特定于编译器/OS的。您可以挂接到现有的内存管理器中,也可以用自己的内存管理程序替换它,并提供一个用于指针验证的专用函数。不过,这可能不是很容易做到的。如果性能至关重要,那么您并不真的希望依赖此功能。

        4
  •  3
  •   4pie0    12 年前

    使用 shared_ptr<> shared_array<> 回想起 shared_ptr<> 仅当提供了适当的Deleter时,才能用于管理分配给数组的内存,否则使用 shared_array<> 管理您的阵列

    A* a_tab=new A[100];
    boost::shared_ptr<A> a_tab_ok(a_tab,ArrayDeleter<A>()); 
    

    //只有在以下情况下才可以

    template <typename T>
        class ArrayDeleter
        {
        public:
            void operator () (T* d) const
            {
                delete [] d; //will delete array!
            }
        };
    

    已提供

        5
  •  2
  •   James Kanze    12 年前

    指针不会告诉你任何东西。您的设计应该:如果 你使用的是动态分配,这是正常的 因为 你的 应用程序要求对象具有特定的生存期,因此 您知道何时正确删除对象。如果对象是 可复制,或者具有与范围相对应的生存期 不要(通常)动态分配。

    当然,在非常低级别的代码中,如果 你正在实施类似 std::vector ,您将拥有 使用某种动态分配,因为大小不是 在编译时已知。但这种分配不应该逃脱; 处理 记忆力

    最后,缓冲区溢出,访问已删除的内存,以及 类似的是未定义的行为。一般来说, 导致异常,并且没有通用的方法 处理它们。(你 可以 通常安排在 这样的事情会发生,但从 信号处理程序,这并没有多大帮助。)一般来说 你想要的是程序崩溃,因为你不知道 它处于什么状态。在极少数情况下 在这种情况下,您必须依靠定义的实现 扩展,如果存在的话。如果使用 /EHa 选项,例如,通常会发生崩溃 将被转换为C++异常。但那是风险投资++ 扩展,但您仍然不知道 程序。如果是因为你破坏了 自由空间竞技场,即使 你抓住了例外(很有可能 当 你打开堆栈)。

        6
  •  2
  •   Martin Fehrs    8 年前

    我知道这根线很旧了。但如果其他人正在阅读这篇文章,他应该知道unique_ptr。shared_ptr确实有开销。计数器存储在堆中。每次访问计数器时,都存在处理器缓存不匹配的风险。unique_ptr的限制更大,但与普通指针相比没有开销。我的建议是,当您不需要引用计数时,更喜欢unique_ptr而不是shared_ptr。 另一个重要的注意事项是,unique_ptr可以很好地与数组配合使用。 如果我没记错的话,从C++17开始shared_ptr也是如此。

        7
  •  1
  •   Saqlain    12 年前

    智能指针是避免此类问题的更好选择(但在使用它们之前,您必须完全了解它们),但我想提及与智能指针相关的性能限制,原因是它们通常使用原子操作,例如Win32 API中的InterlockedIncrement用于引用计数。这些函数明显比普通整数运算慢。我不确定在你的情况下,这么小的绩效罚款是否可以接受。

    我通常所做的是(所以我不必花几天的时间来调试讨厌的错误),在进行实际编码之前,我会在设计和对象生存期上花很多时间,因为我删除了内存,我专门将指针设置为NULL,就我而言,这是一个很好的实践。同样,也许真正的解决方案是在继续之前花更多的时间来确定依赖关系和对象生存时间!