【问题标题】:C++ delete pointer with valid address具有有效地址的 C++ 删除指针
【发布时间】:2011-10-22 07:34:50
【问题描述】:

我正在使用 Poco C++ 库并导致奇怪的问题。 Poco 使用自己的共享指针类SharedPtr 进行内部指针操作。在我的情况下,静态对象Poco::SSLManager 具有证书处理程序对象的SharedPtr 成员。当程序运行结束时,静态对象被删除并且我捕捉到分段错误。 使用 GDB 调试器我看到核心转储并且不理解问题。删除SharedPtr对象(简单操作:delete pObj)时出现段错误,但对象有有效地址,如-0x8fcbed8

为什么删除有效地址的指针会导致分段错误?
可能是因为对象在应用程序的fork副本中创建并在main中销毁?

【问题讨论】:

  • 删除对象指针前检查空指针,删除操作后设置为空。
  • SharedPtr 通常具有ptr->Release() 功能。看看吧
  • @Reddy:在调用delete 之前不要检查null,因为它被定义为对null 指针不执行任何操作。
  • 2 Gasim,年份 ptr 在发布调用之前检查并在之后设置为空。

标签: c++ memory-management fork shared-ptr poco


【解决方案1】:

这是一个非常困难的问题,我不完全理解问题,但我尝试解释它和我的解决方案。 问题是特定于平台的,并且仅在带有 gcc 4.5.5 编译器和 Poco 库的 Gentoo linux 上发生。

我有使用模块(插件)处理不同请求的守护进程。模块和守护进程使用一个使用 poco 库的静态库。在静态库中有代码来创建 SSL 连接并因此创建 SSL 管理器。静态库链接到模块和守护进程。

在工作守护进程结束后,我遇到了问题中描述的分段错误。我将静态库更改为共享库,问题消失了,没有段错误。一切正常。

真的,我不明白,但似乎它是 gentoo 上的 gcc 编译器错误。在其他带有其他 gcc 的 linux 上,所有这些都适用于静态库。

【讨论】:

  • Gentoo linux with gcc 4.5.5 - 错误的 4.4.5 版本
【解决方案2】:

正如其他人所说,这并不是因为您的指针看起来像 0x8fcbed8 这样“好”,它是一个正确的指针。

事实上,如果你使用“delete”,指针会保持它的值。但是你不应该再使用它了。 (在删除之后将其设置为 NULL 是一个很好的做法,这样调试器就会显示为“空”。)

如果您使用 linux 进行开发,有一个工具可以帮助您找出问题所在。这是 valgrind

valgrind  your_program  [args]

(只需在您通常启动的命令前添加“valgrind”即可。如果此处尚未安装 valgrind,则必须在您的发行版中为它提供一个数据包,因为它是一种广泛使用的工具。)

然后 valgrind 将在程序运行时检查您的程序(稍微减慢它),并在您删除不应该删除的内容后立即报告您。 (以及许多其他错误)

【讨论】:

    【解决方案3】:

    一个有效的地址只是一个可访问的地址。这并不意味着它适合删除。您可以 deletenew 返回的内容。如果你没有new它,你就不能delete它。删除静态或自动对象是未定义的行为 - 以及您可能从除 new 之外的任何其他来源获得的行为。

    【讨论】:

    • 此外,您永远不应该删除智能指针产生的任何内容。智能指针被称为“智能”,因为它们自己负责删除。
    • 当然是新的。但是 fork 进程中的新操作,以及在父进程中破坏的静态对象(从共享库创建 - 所以)中的对象存储。我觉得这可能是一场冲突。
    • 你绝对不能跨进程删除。
    【解决方案4】:

    您谈到使用shared pointer。如果该删除是 pObj 上的最后一次删除,则可能是该对象被删除的最后一次。因此,共享指针指向的对象最终将被销毁。在这种情况下,调用 pObj 的 destructor,也许你会从那里得到 Seg Fault。

    另一方面,根据 Poco 库使用的共享指针的实现,可能是您通过调用 delete 来滥用共享指针。

    【讨论】:

    • Poco SharedPtr 看起来像智能指针并使用内部原子计数器。我还检查了我的问题对象(InvalidCertificateHandler)的析构函数。这是一个简单的对象,没有父母,只有 1 个布尔变量。在析构函数中,我看到一些静态对象 SSLManager 方法的调用,但在注释后它的应用程序行为没有改变。
    • 我认为您使用的共享 ptr 错误,但很难猜到。请编辑您的帖子并添加一些代码,例如您构造和操作 Shared Ptr 的行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 2016-07-13
    相关资源
    最近更新 更多