【问题标题】:Memory allocation and deallocation across threads跨线程的内存分配和释放
【发布时间】:2010-09-28 06:05:28
【问题描述】:

我仍在尝试调试一个非常隐秘的内存损坏问题。我遇到了一段代码,它在一个线程上分配内存并在另一个线程上删除它。

我有一种模糊的感觉,认为这是错误的,但我不知道为什么。线程共享进程内存并且对这些结构的访问受到互斥锁的保护,所以我认为一切都会正常工作。但是,有什么我没有看到的危险吗?

【问题讨论】:

    标签: c++ multithreading memory


    【解决方案1】:

    正如@monjardin 的另一个回答所指出的那样,您尝试做的事情本身并没有错。

    另外,您没有提及您遇到此问题的平台等,但如果多线程对您和/或您正在处理的此应用程序是新的,您希望确保您使用的标准支持库是这些库的线程安全版本。在许多环境/平台中,它们同时具有可供开发人员使用的支持库的单线程和多线程版本。如果您使用线程但链接到库的单线程版本,则可能会发生很多不好的事情。例如,在 malloc()free() 的单线程支持库中,它不会为堆提供互斥保护(作为优化)。该库的多线程版本将向堆管理器添加互斥锁保护,以支持一次操作堆的多个线程。 (这只是一个例子)。

    【讨论】:

      【解决方案2】:

      不,这很好,而且很常见,尤其是在使用 CreateThread 的 Windows 编程中,您可以在堆上分配参数,并将参数作为 void * 参数传递给 CreateThread。最简单的做法是让被调用线程在处理完参数后删除它的参数。但是,如果您遇到内存损坏问题,并且您担心一个线程删除另一个创建的内存,也许您应该考虑是否发生双重删除,例如现在负责清理分配的上下文的传输记忆不清楚,可能调用部分和被调用部分都在做?

      【讨论】:

        【解决方案3】:

        请记住,内存管理器本身也必须是线程安全的,而不仅仅是您对内存的使用。检查您的平台文档。

        【讨论】:

          【解决方案4】:

          只要内存的分配和释放得到适当的保护并且你还要确保只有在同一个互斥锁下才能访问结构,我看不出这是一个问题。请注意,这适用于读取和写入访问,而不仅仅是写入访问,因为您需要确保结构在有人从中读取数据时保持在原位。

          是否有可能某处的某些代码试图在互斥保护之外访问这些数据结构?或者更糟糕的是,这些结构中的一些可能会成为 C++ 对象生命周期考虑的牺牲品(例如,它们被销毁是因为它们是通过 boost::shared_ptrs 引用的,并且最后一个 shared_ptr 刚刚退出了建筑物?

          您是否 100% 确定这是内存损坏?另一个看起来非常相似的错误是,某些代码保留了不应保留的引用,并且引用的对象由于内存重新分配而被移动。这并不是一个奇怪的场景,因为向向量中添加另一个元素会触发这种情况(仅举一个例子)。

          【讨论】:

          • 在访问对象时对互斥保护没有严格要求,只要一次只有一个线程“拥有”指向对象的指针。例如,在另一个答案中提到的生产者/消费者模型中
          【解决方案5】:

          危险在于多线程代码更难编写。但是,如果程序是正确的,那么应该没有问题。这可能是 producer/consumer 模式中的常见情况,其中生产线程分配的内存位于 synchronized queue 中并由消费线程释放。

          【讨论】:

            猜你喜欢
            • 2010-11-23
            • 1970-01-01
            • 2020-08-25
            • 1970-01-01
            • 1970-01-01
            • 2011-12-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多