我仍在尝试调试一个非常偷偷摸摸的内存损坏问题。我遇到了一段代码,它在一个线程上分配内存并在另一个线程上删除它。
我有一种模糊的感觉,这是错的,但我不确定为什么。线程共享进程内存,对这些结构的访问受到互斥锁的保护,所以我认为一切都会起作用。但是,我没有看到任何危险吗?答案 0 :(得分:5)
正如@monjardin的另一个回答所指出的那样,你想要做的事情没有任何内在错误。
另外一个想法是,你没有提到平台等等你遇到这个问题,但如果多线程对你和/或你正在使用的这个应用程序来说是新的,你要确保您正在使用的标准支持库是库的线程安全版本。在许多环境/平台中,它们都具有开发人员可用的支持库的单线程和多线程版本。如果您正在使用线程但链接到库的单线程版本,则可能会发生许多不好的事情。例如,在 malloc()和 free()的单线程支持库中,它不会对堆进行互斥保护(作为优化)。库的多线程版本会向堆管理器添加互斥保护,以支持一次操作堆的多个线程。 (这只是一个例子)。
答案 1 :(得分:1)
不,这很好,而且非常常见,特别是使用CreateThread的Windows编程,您可以在堆上分配参数,并将参数作为void *参数传递给CreateThread。最简单的方法是让被调用的线程在完成它们时删除它的参数。但是,如果您遇到内存损坏问题,并且您担心有一个线程删除了另一个创建的内存,那么您可能应该考虑是否发生了双重删除,例如是否转移了哪个上下文现在负责清理已分配的内存内存不清楚,也许调用和被调用部分都在做呢?
答案 2 :(得分:1)
请记住,内存管理器本身也必须是线程安全的,而不仅仅是你对内存的使用。检查您的平台文档。
答案 3 :(得分:0)
危险在于多线程代码更难编写。但是,如果程序是正确的那么应该没有问题。这可能是 producer/consumer 模式中常见的情况,其中生产线程分配放置在 synchronized queue 中并由消费线程释放的内存。
答案 4 :(得分:0)
只要内存的分配和释放得到适当保护和,你也可以确保仅在相同的互斥锁下访问结构时,我真的看不到这是一个问题。请注意,这适用于读写访问,不仅适用于写访问,因为您需要确保在有人从中读取数据时结构保持原样。
某些代码是否有可能尝试在互斥保护之外访问这些数据结构?或者更糟糕的是,这些结构中的某些结构可能会成为C ++对象生命周期考虑的牺牲品(比如,它们被销毁,因为它们是通过boost :: shared_ptrs引用的,而最后一个shared_ptr刚刚退出了建筑物?
您是否100%确定是内存损坏?另一个看起来非常相似的错误是,当某些代码保留在不应该引用的引用上时,引用的对象会因内存重新分配而被移动。这不是一个古怪的场景,因为向向量添加另一个元素可以触发(仅举一例)。