關於QSocket的釋放的一個需要注意的情況(必須先斷開連接)


最近在用QtNetwork編寫服務器程序進行TCP/IP通信,大體過程如下:

1. 創建一個QTcpServer實例,監聽目標IP和端口;

2. 一旦監聽到有連接,獲取和客戶端之間的socket;

3. 使用socket進行通信;

4. 通信結束后,可以手動釋放socket,也可以不管它,在釋放QTcpServer的時候會把其下的所有socket全部自動釋放。

 

在編寫時,我做了如下事:

 

[cpp]  view plain  copy
 
  1. TcpNetwork::TcpNetwork()  
  2. {  
  3.     ...  
  4.     connect(mySocket, SIGNAL(disconnect(QTcpSocket*)), this, SLOT(ServerConnectionLost(QTcpSocket*)));  
  5.     ...  
  6. }  

 

 

[cpp]  view plain  copy
 
  1. TcpNetwork::~TcpNetwork()  
  2. {  
  3.     if (tcpServer != NULL)  
  4.     {  
  5.         delete tcpServer;  
  6.     }  
  7. }  
[cpp]  view plain  copy
 
  1. <pre name="code" class="cpp">void TcpNetwork::ServerConnectionLost(QTcpSocket *socket)  
  2. {     
  3.     if (socket == mySocket)  
  4.     {  
  5.         ...  
  6.         // debug  
  7.         delete mySocket;  
  8.         mySocket = NULL;  
  9.         ...  
  10.     }  
  11. }  



 

 
        

 

 

這樣在關閉程序窗口時會導致崩潰,看了一下QTcpServer的析構函數源碼后發現,在析構時Qt會首先檢查QtcpServer下的socket指針所指向內存是否已被釋放,然后執行每個socket的關閉操作,隨后釋放剛才被檢查過的未被釋放的socket內存,最后釋放QTcpServer。

 

如果將QTcpSocket::disconnect()信號與一個其中帶有釋放socket操作的槽連接起來,那么如果socket還沒有關閉就直接析構QTcpServer,在執行斷開socket這一步時(如果之前已經斷開了就不會再執行這一步了)會觸發帶有刪除socket操作的槽,然而析構函數對此一無所知,緊接着便是析構函數來釋放socket,也就造成了socket的內存的重復釋放,導致崩潰。

 

解決方法:在關閉窗口之前先關閉socket,這樣在析構函數中就不會再執行關閉socket的操作。或者在連接斷開時觸發的含有釋放socket操作的槽中將delete socket改為socket->deleteLater()。

 

http://blog.csdn.net/qq_19672579/article/details/47973409


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM