线程间的内存分配和释放

6

我仍在努力调试一个非常难以察觉的内存损坏问题。我遇到了一段代码,它在一个线程上分配内存,在另一个线程上删除内存。

我有一种模糊的感觉,这是错误的,但我不确定为什么。这些线程共享进程内存,并且通过互斥保护对这些结构的访问,因此我认为一切都应该正常工作。然而,我是否存在任何看不到的危险?

5个回答

6

正如@monjardin另一个答案中所指出的那样,你试图做的事情本质上没有问题。

另外,如果多线程对你来说是新的,或者你正在处理的应用程序是新的,你需要确保你正在使用的标准支持库是线程安全版本的库。在许多环境/平台上,开发人员可以同时使用单线程和多线程版本的支持库。如果你正在使用线程,但链接到单线程版本的库,可能会发生很多糟糕的事情。例如,在单线程支持库中的malloc()free()不会为堆(作为一种优化)提供互斥保护。多线程版本的库将添加互斥保护以支持多个线程同时操作堆。(这只是一个例子)。


2

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


1

没问题,这很好,特别是在使用CreateThread进行Windows编程时,您可能会在堆上分配参数,并将该参数作为void *参数传递给CreateThread。最简单的方法是让被调用线程在完成它们的工作时删除它们的参数。但是,如果您遇到内存损坏问题,并且担心一个线程删除另一个创建的内存,也许您应该考虑是否存在双重删除,比如说当前上下文负责清理分配的内存的转移不清晰,或许两个调用段都在处理它?


0

多线程编程的危险在于它更难编写。然而,如果程序正确,那么就不应该有问题。这可能是在生产者/消费者模式中经常发生的情况,其中生产线程分配放置在同步队列中的内存,并由消费线程释放。


0
只要内存的分配和释放受到适当的保护,并且您确保在相同的互斥锁下访问结构,我真的看不出这会成为一个问题。请注意,这适用于读取和写入访问,而不仅仅是写入访问,因为您需要确保结构在有人从中读取数据时保持在原地。
是否有可能某些代码尝试在互斥保护之外访问这些数据结构?或者更糟糕的是,这些结构中的一些会成为 C++ 对象生命周期考虑的牺牲品(比如说,它们被引用通过 boost::shared_ptrs 并且最后一个 shared_ptr 已经退出了)?
您是否百分之百确定这是内存损坏?另一个非常相似的错误是当某些代码持有不应该持有的引用并且由于内存重新分配而移动了被引用的对象。这并不是一个荒谬的情况,因为向向量添加另一个元素可能会触发这种情况(只是举个例子)。

1
只要一次只有一个线程“拥有”对象指针,访问对象时就不需要严格的互斥保护。例如,在另一个答案中提到的生产者/消费者模型中。 - Tall Jeff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接