www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > > 充電吧
[導(dǎo)讀]做為程序員,最怕什么?Bug?大家都清楚,調(diào)試期的 Bug 并不可怕,那怕是那些神龍見(jiàn)首不見(jiàn)尾的 INT(隨機(jī)、沒(méi)有規(guī)律) Bug。做為嵌入式程序員,也是一樣的。一般來(lái)說(shuō)嵌入式系統(tǒng)都提供了異常分析的方

做為程序員,最怕什么?Bug?大家都清楚,調(diào)試期的 Bug 并不可怕,那怕是那些神龍見(jiàn)首不見(jiàn)尾的 INT(隨機(jī)、沒(méi)有規(guī)律) Bug。

做為嵌入式程序員,也是一樣的。一般來(lái)說(shuō)嵌入式系統(tǒng)都提供了異常分析的方法,特別是強(qiáng)大的調(diào)試工具,這些工具使用在 PC 上編程使用的工具是一樣的,例如:Visual Studio 系列。但是一些專用的、或小的嵌入式系統(tǒng),可能會(huì)提供專用的調(diào)試工具。雖然從功能上來(lái)說(shuō),沒(méi)有微軟提供的 VS 功能強(qiáng)大,使用起來(lái)也不太方便,但也會(huì)提供類似的調(diào)試功能。這里我主要討論的還是微軟提供的工具。
目前,在車載與 PND 市場(chǎng),使用 WinCE 系統(tǒng)的比較多。在 WinCE6.0 系統(tǒng)中,如果應(yīng)用發(fā)生較嚴(yán)重的錯(cuò)誤時(shí),一般都會(huì)彈出系統(tǒng)標(biāo)準(zhǔn)的、令人十分討論的應(yīng)用錯(cuò)誤對(duì)話框。大概提示:XXX.exe出現(xiàn)嚴(yán)重錯(cuò)誤,必須被關(guān)閉。
如何解決此類問(wèn)題呢?
只要能接上調(diào)試串口,或與調(diào)試工具連接,如VS2008等,獲取出錯(cuò)時(shí)的異常信息后,就可以來(lái)分析異??赡艿脑?。
但如果設(shè)備已經(jīng)處于量產(chǎn)狀態(tài),無(wú)法連接輸出 LOG 的串口和調(diào)試 USB 口時(shí),如何能捕捉到異常信息呢?
在無(wú)法徹底解決此類問(wèn)題的情況下,有人就想能不能不讓系統(tǒng)顯示那個(gè)錯(cuò)誤對(duì)話框。為了能使應(yīng)用“優(yōu)美”的退出(網(wǎng)絡(luò)上的說(shuō)法),即程序退出時(shí)不出現(xiàn)述的錯(cuò)誤對(duì)話框,有人曾試著去修改 WinCE 提供的內(nèi)核代碼,但這部分應(yīng)該是屬于未開(kāi)源的部分。所以此方法也行不通的!


解決此類問(wèn)題的根本辦法當(dāng)然是提高編碼的質(zhì)量,然后加強(qiáng)質(zhì)量保證(即測(cè)試),盡量將 Bug 消滅在研發(fā)階段。因?yàn)檠邪l(fā)階段,有大量的調(diào)試工具可以使用,如下述的第一種方法。
在沒(méi)有調(diào)試工具可以依賴時(shí),有沒(méi)有辦法獲取到異常信息呢?方法當(dāng)然是有的,如下述第二種和第三種方法。為什么要說(shuō)第一種方法呢,因?yàn)樗峁┑男畔⑹亲罨A(chǔ)的,是后面兩種方法都要用到的基礎(chǔ)。在這里,我重點(diǎn)推薦的是第三種方法。因?yàn)樗奶幚肀容^獨(dú)立、在 WinCE 系統(tǒng)中比較有效、且方便集成到已有代碼中,實(shí)現(xiàn)異常捕獲。


第一種方法:如果有輸出 LOG 串口可說(shuō)時(shí),串口輸出的異常信息,加 MAP 文件一起分析錯(cuò)誤的出處,可以到函數(shù)一級(jí)。所以要求在調(diào)試時(shí)一定要將對(duì)應(yīng)版本的 MAP 文件一起保留,用于后繼異常問(wèn)題的分析。

對(duì)于如下的測(cè)試代碼:


void?TestCrashFunc(void)
{
??int?*pNullPoint?=?NULL;

??RETAILMSG(1,(L"-----------------------------%drn",pNullPoint));
??*pNullPoint?=?0;
??RETAILMSG(1,(L"-----------------------------%d,%drn",pNullPoint,*pNullPoint));
}

void?CallCrashFunc(void)
{
??TestCrashFunc();
}

void?CSmartDeviceMFCDlg::OnTimer(UINT_PTR?nIDEvent)
{
??//?TODO:?在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值
??if(1?==?nIDEvent)
??{
????KillTimer(1);
????CallCrashFunc();
????
????//?其它的功能
??}
??CDialog::OnTimer(nIDEvent);
}


在 WinCE6.0 和 WinCE7.0 下運(yùn)行時(shí),串口的輸出內(nèi)容基本上是相同的,但在 WinCE7.0 下沒(méi)有出錯(cuò)的對(duì)話框。
串口中輸出的 Crash 信息如下:



Exception?'Data?Abort'?(0x4):?Thread-Id=0780000a(pth=c08e24e0),?Proc-Id=077e000a(pprc=c088da7c)?'SmartDeviceMFC.exe',?VM-active=077e000a(pprc=c088da7c)?'SmartDeviceMFC.exe'
PC=00011738(SmartDeviceMFC.exe+0x00001738)?RA=4002ac4c(coredll.dll+0x0001ac4c)?SP=0004f6a8,?BVA=00000000
Exception?'Raised?Exception'?(0x116):?Thread-Id=0780000a(pth=c08e24e0),?Proc-Id=00400002(pprc=8360b5e0)?'NK.EXE',?VM-active=077e000a(pprc=c088da7c)?'SmartDeviceMFC.exe'
PC=eff6ed60(k.coredll.dll+0x0001ed60)?RA=8052a62c(kernel.dll+0x0000e62c)?SP=d9bbf3b4,?BVA=ffffffff


從對(duì)應(yīng)的 MAP 文件中查到是 TestCrashFunc 函數(shù)出錯(cuò)(PC 指針 0x00001738 + MAP 文件中的 Preferred load address 偏移量),此例中出錯(cuò)時(shí)位置為:0x00001738 + 00010000 = 00011738:



SmartDeviceMFC
?Timestamp?is?539fa9e3?(Tue?Jun?17?10:37:23?2014)
?Preferred?load?address?is?00010000
......
?0001:000006a8????????InitInstance@CSmartDeviceMFCApp@@UAAHXZ?000116a8?f???SmartDeviceMFC.obj
?0001:00000708????????OnCbnDropdownCombo1@CSmartDeviceMFCDlg@@QAAXXZ?00011708?f???SmartDeviceMFCDlg.obj
?0001:00000714????????TestCrashFunc@@YAXXZ??????00011714?f???SmartDeviceMFCDlg.obj
?0001:0000075c????????BeginModalState@CWnd@@UAAXXZ?0001175c?f?i?SmartDeviceMFCDlg.obj
?0001:00000768????????EndModalState@CWnd@@UAAXXZ?00011768?f?i?SmartDeviceMFCDlg.obj
?0001:00000774?????????_GCComboBox@@UAAPAXI@Z???00011774?f?i?SmartDeviceMFCDlg.obj


由此可見(jiàn) WinCE7.0 系統(tǒng)對(duì)這種對(duì)空指針賦值等異常是做了一些處理的,至少不再?gòu)棾瞿莻€(gè)令人十分討厭的對(duì)話框,也不影響后繼其它功能的執(zhí)行。在 WinCE6.0 下如果出現(xiàn)類似的對(duì)話框,則應(yīng)用就會(huì)退出。


第二種方法:使用 __try 和 __except。在開(kāi)源的多媒體播放器 TCPMP 中,就有如下的用法。
先定義兩個(gè)宏,然后將重要的處理線程代碼包含在定義的這兩個(gè)宏中,以捕捉兩個(gè)宏之間代碼出現(xiàn)的異常。這樣做有一個(gè)缺點(diǎn):但代碼量很大時(shí),就需要增加很多對(duì)這兩個(gè)宏的調(diào)用。



#define?SAFE_BEGIN?__try?{
#define?SAFE_END?;}?__except?(SafeException(_exception_info()))?{}


可以看到 WinCE 下的使用方法,與 PC 上 SEH(Structured Exception Handling)是一樣的。如下所示:



__try?
{
???//?guarded?code
}
__except?(?expression?)
{
???//?exception?handler?code
}


以下是 TCPMP 中一個(gè)關(guān)鍵線程的異常處理代碼(TCPMP 線程的代碼,沒(méi)有完整的給出,有興趣的童鞋請(qǐng)自己去看 TCPMP 的源代碼),其中兩個(gè)定義的異常處理宏,將線程的所有代碼包含在內(nèi)。



static?int?ProcessThread(player_base*?p)
{
??int?Result?=?ERR_NONE;

#ifdef?MULTITHREAD
??SAFE_BEGIN

??while?(p->Wnd)
??{
????......
????if?(p->RunProcess)
????{
??????processstate?State;
??????State.Fill?=?p->Fill;

??????p->Timer->Get(p->Timer,TIMER_TIME,&State.Time,sizeof(tick_t));

??????//DEBUG_MSG1(DEBUG_PLAYER,T("Process?Time:%d"),State.Time);

??????Result?=?p->Format->Process(p->Format,&State);

??????if?(Result?==?ERR_SYNCED)
??????{
????????......
??????}
??????else?if?(p->Fill?&&?(Result?==?ERR_END_OF_FILE?||?Result?==?ERR_BUFFER_FULL
????????||?(Result?==?ERR_NEED_MORE_DATA?&&?(p->NoMoreInput?||?State.BufferUsedAfter?>=?p->CurrBufferSize2-2))))
??????{
????????......
??????}

??????......
????}
????......
??}

??SAFE_END
??return?0;
}


此種實(shí)現(xiàn)方法,最最關(guān)鍵是 SafeException() 函數(shù)中分析與記錄異常信息的辦法。
但由于在 TCPMP 中,獲取異常的信息與 TCPMP 的軟件框架結(jié)合在一起。需要移植此部分代碼到其它工程時(shí),需要將有用的代碼分離出來(lái),其實(shí)這個(gè)也比較簡(jiǎn)單。
只要將與 EXCEPTION_POINTERS 相關(guān)的代碼拿出來(lái)即可。



int?SafeException(void*?p)
{
??EXCEPTION_POINTERS*?Data?=?(EXCEPTION_POINTERS*)p;

??//?刪除了無(wú)關(guān)的代碼?-?此部分代碼是?TCPMP?中的代碼,所以未做排版。
??{
????{
??????const?uint8_t*?ContextRecord?=?(const?uint8_t*)?Data->ContextRecord;
??????EXCEPTION_RECORD*?Record?=?Data->ExceptionRecord;

??????switch?(Record->ExceptionCode)
??????{
??????case?STATUS_ACCESS_VIOLATION:???Name?=?T("Access?violation");?break;
??????case?STATUS_BREAKPOINT:???????Name?=?T("Breakpoint");?break;
??????case?STATUS_DATATYPE_MISALIGNMENT:??Name?=?T("Datatype?misalignment");?break;
??????case?STATUS_ILLEGAL_INSTRUCTION:??Name?=?T("Illegal?instruction");?break;
??????case?STATUS_INTEGER_DIVIDE_BY_ZERO:?Name?=?T("Int?divide?by?zero");?break;
??????case?STATUS_INTEGER_OVERFLOW:???Name?=?T("Int?overflow");?break;
??????case?STATUS_PRIVILEGED_INSTRUCTION:?Name?=?T("Priv?instruction");?break;
??????case?STATUS_STACK_OVERFLOW:?????Name?=?T("Stack?overflow");?break;
??????default:??????????????Name?=?T("Unknown");?break;
??????}

??????if?(Record->ExceptionCode?==?STATUS_ACCESS_VIOLATION)
??????{
????????if?(Record->ExceptionInformation[0])
??????????Name?=?T("Write?to");
????????else
??????????Name?=?T("Read?from");
??????}
??????
??????//......?關(guān)鍵是處理?EXCEPTION_POINTERS?結(jié)構(gòu)體相關(guān)的成員
??????//?其它一些相關(guān)的,如可執(zhí)行程序文件名等,根據(jù)需要來(lái)獲取
??}
}


第三種方法:使用函數(shù) AddVectoredExceptionHandler()。
在 WinCE 下使用此函數(shù),需要包含頭文件: TlHelp32.h 和庫(kù)文件: toolhelp.lib。由于此函數(shù)屬于 WinCE 示公開(kāi)的 API,所以幫忙只要以 PC 上為準(zhǔn)。
使用此函數(shù),是向 WinCE 系統(tǒng)注冊(cè)一個(gè)矢量異常處理程序,但有異常發(fā)生時(shí)會(huì)調(diào)用此處理程序。
函數(shù)的原型如下(MSDN),各參數(shù)具體的含義,請(qǐng)參考 MSDN。這里就不做翻譯了。



PVOID?WINAPI?AddVectoredExceptionHandler(__in?ULONG?FirstHandler,?__in?PVECTORED_EXCEPTION_HANDLER?VectoredHandler);

以下代碼,演示了如何使用 AddVectoredExceptionHandler() 函數(shù):
(1) AddVectoredExceptionHandler(1,MyVectoredExceptionHandler);


(2) 定義異常處理程序

LONG?WINAPI?MyVectoredExceptionHandler(struct?_EXCEPTION_POINTERS?*pExceptionInfo)
{
??typedef?ULONG?(WINAPI?*lpGetThreadCallStack)(HANDLE,ULONG,LPVOID,DWORD,DWORD);
??/*?在使用時(shí),必須包含一些頭文件。這些頭文件,需要從?WinCE?的安裝目錄中獲得。
??OS?Versions:?Windows?CE?5.0?and?later.
??Header:?Pkfuncs.h.
??*/
??typedef?struct?_CallSnapshotEx
??{
????DWORD?dwReturnAddr;
????DWORD?dwFramePtr;
????DWORD?dwCurProc;
????DWORD?dwParams[4];
??}CallSnapshotEx;
??//?打印?Dump?信息?
??......
??//?打印?SP?堆棧
??......
??ULONG?*punSp?=?(ULONG?*)pExceptionInfo->ContextRecord->Sp;
??//?獲取線程堆棧調(diào)用
??HMODULE?hCore?=?LoadLibrary(L"coredll.dll");
??if(NULL?!=?hCore)
??{
????lpGetThreadCallStack?pGetThreadCallStack?=?(lpGetThreadCallStack)GetProcAddress(hCore,L"GetThreadCallStack");
????if(NULL?!=?pGetThreadCallStack)
????{
????}
??}
??//?獲取進(jìn)程內(nèi)?dll?信息
??MODULEENTRY32?CurrentModule;
??HANDLE?hSnapShot?=?CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId());
??if((HANDLE)-1?!=?hSnapShot)
??{
????//?調(diào)用??Module32First??和?Module32Next?完成?Module?枚舉
??}
}


是否還需要其它信息來(lái)分析程序出現(xiàn)異常的原因,可以參考 MSDN 中對(duì)結(jié)構(gòu) _EXCEPTION_POINTERS 中各成員的說(shuō)明。然后將有用的信息,寫到 SD 卡等可永久存貯的設(shè)備中。這樣就不必為擔(dān)心找不到用于分析異常的資源,且此記錄的文件中的信息遠(yuǎn)大于串口輸出的異常信息。同時(shí),也可以根據(jù)需要輸入一些應(yīng)用(進(jìn)程)的相關(guān)信息。
可以將此異常捕獲功能的代碼,封裝成一個(gè) LIB 來(lái)供使用程序調(diào)用。


相對(duì)于 PC Windows 下感知程序崩潰(其實(shí)就是運(yùn)行時(shí)的嚴(yán)重錯(cuò)誤)的方法,WinCE 還是比較少的,且真正被用的更是少之又少。
PC 下除了以上第二和第三種方法外,還有以下 3 個(gè)核心的函數(shù)可以感知程序的異常,分別是:
SetUnhandledExceptionFilter(HandleException),功能是確定出現(xiàn)沒(méi)有控制的異常發(fā)生時(shí)調(diào)用的函數(shù)為 HandleException;函數(shù)在 WinCE 上是不可用的,無(wú)100%替代函數(shù)。
_set_invalid_parameter_handler(HandleInvalidParameter),功能是確定出現(xiàn)無(wú)效參數(shù)調(diào)用發(fā)生時(shí)調(diào)用的函數(shù)為 HandleInvalidParameter;
_set_purecall_handler(HandlePureVirtualCall),功能是確定純虛函數(shù)調(diào)用發(fā)生時(shí)調(diào)用的函數(shù)為 HandlePureVirtualCall。


充分利用 Bug 的解決方法,是一個(gè)程序員成長(zhǎng)的必由之路。因?yàn)槌绦騿T的工作不只是編碼,還包括前期設(shè)計(jì)與后期的產(chǎn)品問(wèn)題的修復(fù)等。
好的應(yīng)用,就應(yīng)該像 TCPMP 一樣,在異常來(lái)臨時(shí)能正確的提示用戶,這樣的程序的崩潰也朝“優(yōu)美”邁進(jìn)了一步。同時(shí),也提供的開(kāi)發(fā)人員分析異常的信息:記錄在文件中。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

納祥科技推出太陽(yáng)能+Type-C雙充電自行車前燈方案,方案核心模塊包含太陽(yáng)能板、單片機(jī)、三極管、3顆LED燈珠與1200mAh電池,通過(guò)低功耗單片機(jī)與三極管驅(qū)動(dòng),支持強(qiáng)光/弱光/爆閃3種模式,高流明遠(yuǎn)射程,適配多種車型

關(guān)鍵字: 方案開(kāi)發(fā) 電子方案 自行車前燈方案 納祥科技

慕尼黑2025年9月11日 /美通社/ -- 當(dāng)?shù)貢r(shí)間9月9日,賽力斯動(dòng)力在德國(guó)慕尼黑國(guó)際車展期間舉辦技術(shù)發(fā)布與交流會(huì),正式在海外市場(chǎng)推出全新一代賽力斯超級(jí)增程、高效發(fā)動(dòng)機(jī)和新一代分布式電驅(qū)動(dòng)系統(tǒng),同時(shí)與來(lái)自全球的汽車產(chǎn)...

關(guān)鍵字: 慕尼黑 分布式 發(fā)動(dòng)機(jī) 新能源汽車

慕尼黑2025年9月11日 /美通社/ -- 高端智能電動(dòng)汽車品牌問(wèn)界(AITO)在2025年德國(guó)國(guó)際汽車及智慧出行博覽會(huì)(IAA MOBILITY)上,正式發(fā)布了其最新全球產(chǎn)品陣容——專為中東市場(chǎng)深度本地化打造的AIT...

關(guān)鍵字: AI 智能駕駛 測(cè)試 生態(tài)系統(tǒng)

舍弗勒首次為中國(guó)頭部車企大規(guī)模生產(chǎn)高壓逆變磚 天津工廠一年內(nèi)完成量產(chǎn)準(zhǔn)備,逆變器模塊性能參數(shù)顯著提升 與合作伙伴羅姆半導(dǎo)體共研尖端碳化硅技術(shù),效率更高、性能更優(yōu) 模塊化可擴(kuò)展設(shè)計(jì)使逆變磚易于集成,可廣泛...

關(guān)鍵字: 逆變 高壓 逆變器 集成

舍弗勒以"專注驅(qū)動(dòng)技術(shù)的科技公司"為主題亮相IAA MOBILITY 2025(B3館B40展臺(tái)) 合并緯湃科技后首次亮相IAA MOBILITY,展示拓展后的汽車產(chǎn)品組合 憑借在軟件、...

關(guān)鍵字: 電氣 軟件 驅(qū)動(dòng)技術(shù) BSP

拉斯維加斯2025年9月11日 /美通社/ -- 在9月8日至11日舉辦的RE+ 2025展會(huì)上,全球綜合儲(chǔ)能解決方案供應(yīng)商德賽電池(Desay Battery)全面展示了其創(chuàng)新成果,并宣布與深圳市華寶新能源股份有限公司...

關(guān)鍵字: 電池 電芯 人工智能 鋰電

香港2025年 9月12日 /美通社/ -- 全球領(lǐng)先的互聯(lián)網(wǎng)社區(qū)創(chuàng)建者 - 網(wǎng)龍網(wǎng)絡(luò)控股有限公司 ("網(wǎng)龍"或"本公司",香港交易所股票代碼:777)欣然宣布,其子公司My...

關(guān)鍵字: AI 遠(yuǎn)程控制 控制技術(shù) BSP

慕尼黑2025年9月12日 /美通社/ -- 慕尼黑當(dāng)?shù)貢r(shí)間9月10日,在2025德國(guó)國(guó)際汽車及智慧出行博覽會(huì)(IAA MOBILITY)上,國(guó)際獨(dú)立第三方檢測(cè)、檢驗(yàn)和認(rèn)證機(jī)...

關(guān)鍵字: 測(cè)試 慕尼黑 模型 HUBER

上海2025年9月12日 /美通社/ -- 近日,國(guó)際獨(dú)立第三方檢測(cè)、檢驗(yàn)和認(rèn)證機(jī)構(gòu)德國(guó)萊茵TÜV大中華區(qū)(簡(jiǎn)稱"TÜV萊茵")為上海...

關(guān)鍵字: 測(cè)試 信息安全 安全管理 開(kāi)關(guān)

廣州2025年9月12日 /美通社/ -- 9月11日,由國(guó)際獨(dú)立第三方檢測(cè)、檢驗(yàn)和認(rèn)證機(jī)構(gòu)德國(guó)萊茵TÜV大中華區(qū)(簡(jiǎn)稱"TÜV萊茵"...

關(guān)鍵字: 數(shù)字化 供應(yīng)鏈 控制 電子
關(guān)閉