關於 pure virtual method called terminate called without an active exception 解決方案

一、問題描述

  因爲最近在學習 C++ 並實踐導師給的項目,在實踐的過程中基本每天都會踩坑,今晚遇到了一個困擾了我好幾個小時的問題。具體問題是當程序運行時總會報 pure virtual method called terminate called without an active exception 這個錯誤。

在這裏插入圖片描述
  對於這個問題我在網上查詢了很多資料都沒有太好的解決方案,對於我的業務代碼基本是這樣的:

void func()
{
	while(true)
	{
		connfd = accept();
		CWork work;
		work.setConnfd(connfd);
		m_thread_pool.addWork(work);
	}
}

void f()
{
	work.run();
}

  主要的代碼邏輯就是前端接收 TCP 請求,將其封裝爲 CWork 後交給線程池來進行處理(具體是將其添加到任務隊列中,然後又業務線程從任務隊列中不斷獲取任務執行)。

二、解決思路

  首先在網上經過查詢後我發現這個錯誤的主要原因是當前對象已經被銷燬或者正在被銷燬,導致最終調用到其基類的 虛方法 上,最終報出了這個錯誤。爲了驗證這個思路我首先在該對象(work)的析構函數中進行了打印,在運行時果然發現在執行到 work 對象的 run 方法之前該對象就已經被銷燬了。

  後來我又做了很多嘗試,最終才發現因爲自己對於 C++ 語法不熟練,導致對於對象作用範圍的判斷出現了失誤。在 C++ 中我們主要有三種創建對象的方法:

  • Test test1; // 棧中分配 ,由操作系統進行內存的分配和管理
  • Test test2 = Test; // 棧中分配 ,由操作系統進行內存的分配和管理
  • Test *test3=new Test(); // 堆中分配 ,由管理者進行內存的分配和管理,用完必須delete(),否則可能造成內存泄漏

  而我上面的那種創建方式剛好就是第一種方式,也就是說當前對象在棧中進行分配的,且因爲其作用於爲 while 循環中,所以每一輪循環都會創建一個新的 work 對象,且前一個對象因爲被保存在棧上,所以循環結束後就已經被銷燬。因此,這時再在外部對其進行調用,肯定就會報錯了。

三、解決方案

  知道了問題出現的原因,對於問題的解決就比較簡單了,因爲我的項目是針對網絡連接請求的,因此必須保證每一個連接都對應一個新的 work 對象,但是我們還需要保證它不會在本輪循環結束後就被銷燬。因此,我們直接使用第三種創建對象的方式 Test *test3=new Test()即可解決該問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章