Qt:发出信号会导致内存泄漏吗?如果他们连接的 slot/thread 被阻止会怎样?

Qt: Can emitting signals cause a memory leak? What happens if their connected slot/thread is blocked?

当要捕获信号的目标线程被阻塞时,信号及其占用的内存会怎样?

信号是否进入队列?
队列是否溢出,我们丢失了一些信号?
如果不是,我们会发生内存泄漏吗?

当发出信号并通过排队连接连接到某些对象时,每个连接都会在堆上分配一个事件,并发布到与接收对象关联的事件队列中。

一旦事件被处理,它就会被删除。虽然事件未被处理,但它需要一些堆 space,因此如果您继续将事件发布到队列但它不会在另一端耗尽,您会不断增加内存消耗 w/o 减少它。您可以将其视为内存泄漏。未指定队列的大小,但很可能您无法溢出它 w/o 导致未定义的行为(或已定义的异常,例如 std::bad_alloc)。

一般情况下,信号产生的速度可能比消耗的速度快。仅当您使用排队连接时才会发生这种情况。这通常发生在多线程代码中(默认使用排队连接)或者如果您使用标志 Qt::QueuedConnection.

设置连接

如果您的连接没有排队,则不会发生这种情况,因为信号在发出后立即由插槽同步处理。所以未处理的信号不会在队列中等待。

所以当你有一个排队的连接并且生成和发出信号的速度快于消耗事件循环可以处理它们时,它们当然被排队,它们占用内存(堆)并且如果运行 足够长的时间,内存最终会耗尽 (您可能会观察到 RAM 交换到磁盘,减慢系统速度使其无法使用)。当您询问内存泄漏时 - 这可能不会发生。但是内存泄漏在这里是您最不关心的问题。

所以你一定要避免这种产生信号太快的情况。如何做到这一点有很多选择。例如,您可以在发射方中设置一个计时器,如果最新信号在小于 100 毫秒之前发射,则不允许发射信号。 (我在我的应用程序的进度条中使用它。)

另一种选择是实施 two-way 通信,其中发射器将发送一个信号,接收器将对其进行处理,并将发回另一个信号作为确认处理已完成的响应,并且该信号将被原始信号的发射器接收,通知它现在可以安全地发射另一个信号了。

另一种选择是不使用信号和槽并直接调用方法,但当然您需要使用原子或锁定互斥锁来实现适当的同步机制。请注意,在这种情况下,信号不会在队列中等待,但线程可能会执行不佳,因为它们经常相互阻塞。

所以选择哪种方法取决于你。但是你必须绝对避免这种情况,当你发射信号的速度比你在与排队连接连接的插槽中处理它们的速度更快时。