QT編寫上位機程序一定要初始化變量以及謹慎操作指針


背景:

  在編寫QT上位機界面時,界面在運行的時候經常出現卡死或者直接掛掉的怪現象。

正文:

  上位機有個函數為check_receive();該函數的作用為定時調用循環檢測USB是否有數據。若有,則將信息打印到界面窗體上。界面上有兩個QTableWidget窗體

"ui->can1tableWidget與ui->can2tableWidget",根據傳上來的的數據某個字節信息為1、或2來打印到對應的窗體上。代碼如下:

QTableWidget *canselWidget = NULL;
unsigned int CANSelCnt;

if(CANData.CANSel == 1)
{
    CANSelCnt = 第1個窗體顯示的行數;    //偽代碼
    canselWidget = ui->can1tableWidget ;
}
else if(CANData.CANSel == 2)
{
    CANSelCnt = 第2個窗體顯示的行數;    //偽代碼 
    canselWidget = ui->can2tableWidget ; 
} 
//接着即使用canselWidget來對界面進行操作。

接着,總會出現,QT上位機界面直接卡死甚至掛掉的問題。觀察現象發現,APP在顯示數據窗體時即瘋狂地新增新的行數。再研究代碼,然后將CANSelCnt打印出來,發現其值為一個很大的隨機值。

解決方案:CANSelCnt 在定義的時候要初始化!!!

接着運行上位機發現,APP顯示數據窗體不再瘋狂的新增行數了。可還是出現掛掉的現象!!
進一步調試才發現若是CANData.CANSel的值不是為1、2那會出現什么情況! 就會對canselWideget這個NULL指針進行操作!更改代碼如下:

switch(CANData.CANSel)
{
    case 1:
        CANSelCnt = 第1個窗體顯示的行數;    //偽代碼
        canselWidget = ui->can1tableWidget ;
         break;
    case 2:
        CANSelCnt = 第2個窗體顯示的行數;    //偽代碼 
        canselWidget = ui->can2tableWidget ; 
        break;
    default:
        // 防止后續代碼對空指針進行操作,直接返回。
        return;
}

 

總結:

1、此處代碼寫的非常不小心,犯如此低級的錯誤卻花費了1天多的時間(還以為是下位機沒配置好!)!下次一定要把握住程序運行的每個通路,杜絕此現象再次發生。

 

2、由於之前一直在寫下位機代碼,所以不賦初值的習慣也帶入到這里,出了這次慘痛教訓!

 

 

/* 以下內容,理解還是有偏差,等理解通了,再重開一篇博客來寫
* 已重新了一篇博客,名稱為"下位機多個".c, .h"文件的相互包含及排版".
* 2016年5月6日
*/

 

附:

  多個".c"文件包含一個".h"文件處理方法

 

  在下位機,為何會經常出現不賦初值的情況發生。(應該說是在聲明的時候不會賦初值。)

  首先,最重要的是,下位機保存全局變量的區域為掉電易失區域,所以得到的變量值會為默認"0"值,嚴謹的做法還是會初始化全局變量。

  其次,在多個".c"文件包含一個".h"文件的情況下,若在".h"文件中賦初值,則相當於在其內即聲明又定義了,那么編譯時,即會出現如下報錯:

  keil *** ERROR L104: MULTIPLE PUBLIC DEFINITIONS (報錯信息不完整,只挑了重點部分)

  所以說,有多個".c"文件需要包含該".h"文件時,不能進行進行變量的定義,只能進行聲明!然后在"main函數"內對其進行初始化操作。

  否則會出現以上錯誤,即重復定義!

 

那么多個"c"文件包含一個".h"文件具體該如何操作呢?

  我自己當時的錯誤想法既是:

  在".h"文件內,聲明全局變量、函數,譬如uchar aa;void sum(uchar aa); 然后多個".c"文件#include該".h"文件,結局很顯然,重復定義錯誤跑不掉。

  何不使用 #ifndef #define #endif ?結果證明並沒有什么卵用。

  正確的做法是,

  在".c"文件內聲明全局變量、函數,譬如uchar aa;void sum(uchar aa);,並在".c"文件內實現該函數。

  然后,在".h"文件,將變量aa,函數void sum(uchar aa);聲明為extern,這樣,其他".c"包含該".h"文件即不會提示重復定義,也可以調用其內部的函數。

  其實這種做法其實相當於某個需要調用該".c"文件的其他"XXX.c"文件在其文件內 extern 該“.c"文件內實現的函數及定義的變量。若是多個文件需要使用使用,每個".c"文件都需 extern 同樣的變量和函數,顯然在做重復工作,於是就將它放在一個".h"文件,多個".c"文件需要調用時直接包含該".h"文件就可以實現 extern 了。

 

記錄地點:深圳WZ

記錄時間: 2015年12月18日 18:55:57


免責聲明!

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



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