QT析构崩溃问题
问题原因:
析构函数崩溃的原因可能有很多,但通常是由于在析构函数中访问了已经被删除或释放的对象指针或内存区域引起的。可能是由于以下原因导致析构函数崩溃:
-
对象被重复删除:如果您在程序中多次删除同一个对象,可能会导致析构函数崩溃。确保您只在需要时删除对象,并且只删除一次。
-
对象指针为空:如果您在析构函数中访问一个空指针,程序就会崩溃。确保在访问对象指针之前,该指针已经被正确初始化。
-
内存泄漏:如果您的程序中存在内存泄漏,可能会导致析构函数崩溃。确保您在程序中正确管理内存,并在不需要时释放对象。
一个容易被忽视的原因
- 线程池
在QT中使用线程池时,需要注意线程池的析构问题。一般来说,线程池的析构需要确保所有线程都已经退出并释放资源,否则可能会导致内存泄漏或其他问题。
在QT中,可以使用QThreadPool类来实现线程池。QThreadPool类提供了一个全局的线程池实例,可以通过QThreadPool::globalInstance()方法获取。在使用线程池时,可以通过QThreadPool::start()方法启动一个任务,并将任务对象传递给该方法。线程池会自动管理线程的创建和销毁,并在任务执行完成后将线程返回线程池。
在析构线程池时,可以通过QThreadPool::waitForDone()方法等待所有任务执行完成,并等待所有线程退出。该方法会阻塞当前线程,直到所有任务执行完成并所有线程退出。在等待完成后,可以调用QThreadPool::clear()方法清空线程池中的所有任务,并释放所有线程的资源。
需要注意的是,在使用线程池时,需要确保任务对象的生命周期正确管理,避免出现内存泄漏或其他问题。一般来说,可以将任务对象设置为QObject的子类,并在任务执行完成后自动释放。同时,需要注意避免在任务中访问已经被析构的对象或资源,避免出现悬挂指针或其他问题。
- 类的状态不确定
QString是一个类,它的内部结构比较复杂,包括指向数据的指针、数据长度、引用计数等信息。使用memset将会清空这些信息,可能会导致QString对象的状态不正确,进而导致程序出现未定义的行为
/* 分包分送句柄 */
typedef struct
{
quint32 last_send_time_ms;
quint32 hw_send_err_times;
uint32_t wait_send_size;
uint32_t current_send_index;
uint32_t data_total_size;
uint8_t *buf_ptr;
EOL_SEND_HW_Typedef_t com_hw; /**< 通讯硬件选择 */
QString channel_num; /**< 通讯硬件端口 */
}SEND_TASK_LIST_Typedef_t;
eol_protocol::eol_protocol(QObject *parent)
: QObject{parent}
{
cq_obj = new CircularQueue(CircularQueue::UINT8_DATA_BUF, CircularQueue::CQ_BUF_4K, this);
if(nullptr == cq_obj)
{
qDebug() << "eol create cq faild";
}
/* !!!这是个有问题的初始化!!!初始化分包发送句柄 */
memset(&send_task_handle, 0, sizeof(SEND_TASK_LIST_Typedef_t));
/* 定时器初始化 */
timer_init();
}