




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第3講 錯(cuò)誤處理和結(jié)構(gòu)化異常處理糾正錯(cuò)誤攔截異常增強(qiáng)程序抵抗力講師:Gamebaby Rock Sun第3講 主要內(nèi)容1.錯(cuò)誤碼和詳細(xì)錯(cuò)誤信息的獲取2.結(jié)構(gòu)化異常處理的基本框架3.結(jié)構(gòu)化異常處理的使用4.結(jié)構(gòu)化異常處理和C+異常處理的比較5.在VC+中混用結(jié)構(gòu)化異常處理和C+異常處理6.封裝自己的異常模塊引言現(xiàn)代高質(zhì)量的應(yīng)用程序應(yīng)具備從可預(yù)料錯(cuò)誤中恢復(fù)的能力在遇到錯(cuò)誤時(shí)可以優(yōu)雅的通知用戶錯(cuò)誤原因錯(cuò)誤內(nèi)容并請(qǐng)求用戶干預(yù),最終從錯(cuò)誤中恢復(fù)雖然軟件邏輯正確,但是從根本上避免不了各種異常,例如:除零錯(cuò)誤、訪問無(wú)效內(nèi)存等一般錯(cuò)誤都可以得到適當(dāng)?shù)奶幚?,但是異常往往?huì)造成程序終止執(zhí)行健壯的程序應(yīng)該都具備處理
2、錯(cuò)誤和異常的能力,最壞情況下可以通知用戶,并優(yōu)雅的退出程序線程最終錯(cuò)誤碼在Windows平臺(tái)上,每個(gè)線程都有一個(gè)線程本地存儲(chǔ)變量(TLS)用于存儲(chǔ)當(dāng)前線程最后一個(gè)錯(cuò)誤碼的值一般情況下,調(diào)用API出錯(cuò)時(shí),API內(nèi)部會(huì)設(shè)置該值為一個(gè)預(yù)定義并指定格式的無(wú)符號(hào)32位整數(shù)應(yīng)用程序在得到API返回值確定調(diào)用API失敗的情況下可以通過調(diào)用GetLastError得到這個(gè)錯(cuò)誤碼,從而得到關(guān)于API錯(cuò)誤的進(jìn)一步信息有了錯(cuò)誤碼,可以使用FormatMessage得到關(guān)于錯(cuò)誤碼的詳細(xì)信息應(yīng)用程序自定義的函數(shù)內(nèi)部也可以在出錯(cuò)時(shí)調(diào)用SetLastError方法設(shè)置自定義的錯(cuò)誤碼,從而可以模擬成一個(gè)API式的函數(shù)應(yīng)用程序
3、可以通過調(diào)用CaptureStackBackTrace函數(shù)捕獲出錯(cuò)時(shí)的棧快照錯(cuò)誤碼格式位313029282716150用途嚴(yán)重性系統(tǒng)錯(cuò)誤碼保留位設(shè)備代碼異常代碼含義0 成功1 供參考2 警告3 錯(cuò)誤0 系統(tǒng)定義1 自定義總為0系統(tǒng)設(shè)備碼具體錯(cuò)誤碼一些常用的錯(cuò)誤提示技巧可以通過調(diào)用MessageBeep函數(shù)發(fā)出一個(gè)短促的錯(cuò)誤提示音告知用戶出現(xiàn)錯(cuò)誤窗口應(yīng)用程序可以通過調(diào)用FlashWindow或FlashWindowEx閃爍窗口提示用戶程序可以通過調(diào)用FatalAppExit函數(shù)顯示一個(gè)出錯(cuò)信息消息框后退出.應(yīng)用程序可以通過調(diào)用FormatMessage函數(shù)得到錯(cuò)誤碼的幫助信息,然后顯示給用戶調(diào)用
4、GetLastError和FormatMessage示例CaptureStackBackTrace調(diào)用示例正確認(rèn)識(shí)異常異常是在程序執(zhí)行期間發(fā)生的,要求軟件能在正常控制流程之外執(zhí)行的事件(掌握異常分析的難點(diǎn))異常往往是由指令序列的執(zhí)行導(dǎo)致的,如被零除或試圖訪問無(wú)效內(nèi)存地址等軟件本身也可以顯式的拋出一個(gè)異常,很多C/C+庫(kù)函數(shù)及類都有拋出異常的版本結(jié)構(gòu)化異常處理Structured Exception Handling SEHWin32API支持結(jié)構(gòu)化的異常處理,既可以處理硬件異常也可以處理軟件異常結(jié)構(gòu)化異常處理不同于C+異常處理結(jié)構(gòu)化異常處理本質(zhì)是C風(fēng)格的異常處理,即函數(shù)加結(jié)構(gòu)形式的處理方式結(jié)構(gòu)
5、化異常處理給程序?qū)Ξ惓L幚淼娜婵刂?同時(shí)提供對(duì)調(diào)試的支持,并且對(duì)所有編程語(yǔ)言環(huán)境都適用Win32結(jié)構(gòu)化異常處理機(jī)制結(jié)構(gòu)化異常處理主要通過編譯器支持提供給開發(fā)者結(jié)構(gòu)化異??梢杂绍浖?也可以由硬件引起,既可以用在RING3層用戶代碼,也可以用于RING0層內(nèi)核驅(qū)動(dòng)代碼中與C+異常處理不同,結(jié)構(gòu)化異常中程序需要通過調(diào)用RaiseException函數(shù)來(lái)引發(fā)一個(gè)自定義異常當(dāng)異常發(fā)生時(shí),CPU將異常發(fā)生那一條指令停止執(zhí)行,并將控制權(quán)交給系統(tǒng)系統(tǒng)接到控制權(quán)后先保存當(dāng)前線程的機(jī)器狀態(tài)和描述異常的信息,然后查找針對(duì)此異常的處理程序入口發(fā)生異常線程的狀態(tài)用CONTEXT結(jié)構(gòu)保存(寄存器狀態(tài))也被稱為上下文
6、記錄,異常描述則用EXCEPTION_RECORD保存(兩個(gè)結(jié)構(gòu)指針合成EXCEPTION_POINTERS結(jié)構(gòu))異常信息可以通過GetExceptionInformation函數(shù)得到(返回EXCEPTION_POINTERS結(jié)構(gòu)指針)異常信息typedef struct _EXCEPTION_RECORD DWORD ExceptionCode; DWORD ExceptionFlags; struct _EXCEPTION_RECORD* ExceptionRecord; PVOID ExceptionAddress; DWORD NumberParameters; ULONG_PTR E
7、xceptionInformationEXCEPTION_MAXIMUM_PARAMETERS; EXCEPTION_RECORD, *PEXCEPTION_RECORD;異常記錄中的信息:標(biāo)識(shí)異常類型的異常碼標(biāo)識(shí)異常是否繼續(xù)的標(biāo)志;在不可繼續(xù)的異常之后繼續(xù)執(zhí)行將引發(fā)另一個(gè)異常到下一個(gè)異常記錄的指針;發(fā)生嵌套異常時(shí)此信息有助于產(chǎn)生異常信息鏈表異常發(fā)生的地址(虛擬空間地址)提供異常附加信息的32bit參數(shù)數(shù)組context在線程一講中詳細(xì)介紹,現(xiàn)在只需知道它其實(shí)就是寄存器狀態(tài)即可異常處理過程(函數(shù))搜索順序1、若進(jìn)程是被調(diào)試執(zhí)行,那么系統(tǒng)先通知進(jìn)程的調(diào)試進(jìn)程(在調(diào)試中詳細(xì)講解調(diào)試進(jìn)程)2、如果進(jìn)
8、程未被調(diào)試,或調(diào)試進(jìn)程不能處理此異常,那么系統(tǒng)就搜索發(fā)生異常線程的堆??蚣苷业娇赡艿漠惓L幚沓绦?、若線程沒提供異常處理過程,或者提供的異常處理過程無(wú)法處理該異常,那么系統(tǒng)將再次嘗試通知進(jìn)程的調(diào)試進(jìn)程4、若進(jìn)程未被調(diào)試或調(diào)試進(jìn)程仍無(wú)法處理該異常,那么系統(tǒng)最終依據(jù)異常類型提供默認(rèn)的處理過程5、對(duì)于大多數(shù)異常來(lái)說,系統(tǒng)默認(rèn)處理就是調(diào)用ExitProcess終止進(jìn)程的執(zhí)行6、內(nèi)核模式下的異常若最終無(wú)處理過程,那么系統(tǒng)就調(diào)用ExitWindows(很多時(shí)候是藍(lán)屏)結(jié)構(gòu)化異常處理框架結(jié)構(gòu)化異常處理框架由下面幾個(gè)基本部分組成:代碼保護(hù)體;過濾表達(dá)式;異常處理塊;在VC/C+中:代碼保護(hù)體是使用_try包含
9、的程序代碼段;過濾表達(dá)式是_except()關(guān)鍵字包含的一個(gè)過濾表達(dá)式/函數(shù),并緊跟_try塊之后可以有多個(gè)異常處理塊就是_except后的包含的復(fù)合語(yǔ)句其它語(yǔ)言環(huán)境中如果支持結(jié)構(gòu)化異常處理請(qǐng)查看相應(yīng)的幫助文檔中的詳細(xì)說明異常處理過濾表達(dá)式當(dāng)_try塊中的代碼發(fā)生異常時(shí),此_try塊之后的_except()中的表達(dá)式就被調(diào)用該表達(dá)式通常返回下面值之一:EXCEPTION_CONTINUE_SEARCH,繼續(xù)查找,即本_except塊不能處理此異常EXCEPTION_CONTINUE_EXECUTION,返回_try塊中的異常代碼處繼續(xù)執(zhí)行,即異常已被正常處理EXCEPTION_EXECUTE_
10、HANDLER,執(zhí)行_except后中的代碼,即執(zhí)行異常處理代碼,不返回到_try中過濾表達(dá)式可以是一個(gè)簡(jiǎn)單表達(dá)式,或者是一個(gè)函數(shù)在過濾表達(dá)式中可以調(diào)用GetExceptionCode和GetExceptionInformagtion函數(shù)取得正在處理的異常信息以上兩個(gè)函數(shù)不能在過濾函數(shù)中調(diào)用,但其返回值可以作為參數(shù)傳遞給異常過濾函數(shù)終止處理塊終止處理是結(jié)構(gòu)化異常處理特有的語(yǔ)法元素終止處理是提供給開發(fā)者用于保證在控制流離開特定代碼保護(hù)體(_try塊)時(shí)總是被調(diào)用執(zhí)行的代碼塊機(jī)制終止處理由以下元素組成:代碼保護(hù)體(_try塊)在控制流離開保護(hù)體時(shí)執(zhí)行的終止代碼塊(_finally塊)當(dāng)前_try塊
11、所屬線程在_try塊內(nèi)終止時(shí),系統(tǒng)將無(wú)法保證調(diào)用_finally塊(如調(diào)用:ExitThread或ExitProcess退出線程時(shí))_finally總被保證無(wú)論_try塊中的代碼有無(wú)異常,都將被執(zhí)行即使在_try塊中調(diào)用return、goto、break、或continue等語(yǔ)句顯示改變代碼控制流,_finally塊一樣被執(zhí)行為了提高性能,SEH中建議使用_leave語(yǔ)句代替_try塊中的return或goto語(yǔ)句結(jié)構(gòu)化異常處理的語(yǔ)法基本異常處理框架:_try/代碼保護(hù)體/其實(shí)就是正常的邏輯代碼_except(filter-expression)/異常處理塊注意_try和_except一一配對(duì)
12、,一個(gè)_try后只能跟一個(gè)_except,若要多個(gè)_except只能在_try塊中再嵌套_try和_except塊結(jié)構(gòu)化異常處理的語(yǔ)法終止處理語(yǔ)法_try/代碼保護(hù)體_finally/終止執(zhí)行塊在終止處理塊中可以通過調(diào)用BOOL AbnormalTermination(void);方法確定之前的_try塊是否是順序終止,即_try塊的是否被執(zhí)行到,其它情況都視為非順序終止(包括異常終止)_finally塊_finally塊的執(zhí)行可以由下列任何一種方式終止:執(zhí)行塊中最后語(yǔ)句并接著執(zhí)行_finally塊后的語(yǔ)句使用正常的控制語(yǔ)句(return、break、continue、goto)離開使用lon
13、gjmp或進(jìn)入到異常處理塊_finally塊與_try塊通常在相同的函數(shù)體中,因此_finally塊中可以正常訪問函數(shù)的局部變量(變量要聲明在_try和_finally之外,對(duì)應(yīng)的仍然遵守C/C+語(yǔ)言關(guān)于復(fù)合語(yǔ)句的語(yǔ)法要求)RaiseException與C+ throw語(yǔ)法形式具體實(shí)現(xiàn)不同,SEH中要拋出一個(gè)自定義異常需要調(diào)用函數(shù)RaiseExceptionvoid WINAPI RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR* lpA
14、rguments);從函數(shù)的參數(shù)可以看出,該函數(shù)其實(shí)就是為了填充一個(gè)EXCEPTION_RECORD結(jié)構(gòu),參數(shù)其實(shí)就是結(jié)構(gòu)中的成員,含義也相同RaiseException調(diào)用示例結(jié)構(gòu)化異常使用提要在第一講中有一個(gè)分段提交內(nèi)存頁(yè)面的例子,演示了如何利用結(jié)構(gòu)化異常處理來(lái)巧妙的提交物理頁(yè)面的例子一個(gè)_try塊要么跟隨一個(gè)_finally塊要么跟隨一個(gè)_except塊,不能同時(shí)跟_finally塊和_except塊_try塊中可以嵌套別的_try_finally塊或_try_except塊_finally塊不可以再嵌套SEH塊_except的復(fù)合語(yǔ)句中可以再嵌套SEH塊通過嵌套可以組合出想要的類似_t
15、ry后即跟_finally塊也跟_except塊的效果很多時(shí)候可以將_finally和_except等理解為函數(shù)調(diào)用,尤其_exceptUnhandledExceptionFilter如果所有的_except塊表達(dá)式都不能處理某個(gè)異常,并且都返回了EXCEPTION_CONTINUE_SEARCH,此時(shí)異常無(wú)法得到恰當(dāng)?shù)奶幚?進(jìn)程會(huì)被系統(tǒng)接管并異常退出通過調(diào)用UnhandledExceptionFilter這個(gè)特殊的異常過濾函數(shù)可以最終攔截此類異常并報(bào)告一個(gè)關(guān)于異常信息的對(duì)話框使得調(diào)試程序有機(jī)會(huì)接管異常進(jìn)程通常在線程函數(shù)的最頂層設(shè)置這個(gè)異常攔截器,再去執(zhí)行線程需要的邏輯這樣就能使發(fā)生異常的程序
16、有機(jī)會(huì)在異常時(shí)轉(zhuǎn)入調(diào)試模式,讓開發(fā)人員有機(jī)會(huì)調(diào)試異常的程序(很多時(shí)候有些異常是很難捕捉的,如果不能在出現(xiàn)時(shí)轉(zhuǎn)入調(diào)試可能將無(wú)法重現(xiàn)這個(gè)異常)通過調(diào)用SetErrorMode設(shè)置SEM_NOGPFAULTERRORBOX值可以屏蔽這個(gè)異常提示框,此時(shí)程序自動(dòng)退出,沒有任何提示(此特性并不友好)Win32向量化異常處理Vectored Exception Handler對(duì)于多層嵌套的SEH來(lái)說,外層的_try_except語(yǔ)句塊可能沒有機(jī)會(huì)處理被內(nèi)層嵌套攔截的異常對(duì)于一般軟件來(lái)說,這不是太大的問題,但是當(dāng)內(nèi)層嵌套的軟件是第三方的庫(kù)函數(shù),并且內(nèi)部以不友好的方式處理了異常,比如:異常退出進(jìn)程了事,這對(duì)整
17、個(gè)程序?qū)⒃斐珊懿焕挠绊懘藭r(shí)可以利用向量化異常處理來(lái)在正常的SEH之前以合適的方式攔截和處理異常通過AddVectoredExceptionHandler函數(shù)可以添加向量化異常處理過濾函數(shù)調(diào)用RemoveVectoredExceptionHandler可以移除一個(gè)已添加的向量化異常處理過濾函數(shù)AddVectoredExceptionHandlerPVOID WINAPI AddVectoredExceptionHandler(ULONG FirstHandler,PVECTORED_EXCEPTION_HANDLER VectoredHandler);FirstHandler為0時(shí),Vecto
18、redHandler過濾函數(shù)總是被添加到向量異常處理過濾函數(shù)鏈表的末尾VectoredHandler過濾函數(shù)原型為:LONG CALLBACK VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo);系統(tǒng)只接受過濾函數(shù)的兩種返回值:EXCEPTION_CONTINUE_EXECUTION表示異常已經(jīng)被處理,并返回異常處繼續(xù)執(zhí)行;EXCEPTION_CONTINUE_SEARCH則繼續(xù)搜索合適的異常處理塊(下一個(gè)過濾函數(shù)或異常過濾表達(dá)式)AddVectoredExceptionHandler的返回值表示當(dāng)前添加的向量異常過濾函數(shù)的句柄,程序保存該值,
19、并最終傳遞給RemoveVectoredExceptionHandler移除該過濾函數(shù)如果進(jìn)程添加了向量化結(jié)構(gòu)異常過濾函數(shù),那么系統(tǒng)搜索異常處理的順序會(huì)發(fā)生變化,系統(tǒng)將首先將異常傳遞給該進(jìn)程的調(diào)試進(jìn)程,之后就遍歷這個(gè)鏈表,如果鏈表中所有的函數(shù)都返回EXCEPTION_CONTINUE_SEARCH則按原來(lái)的順序搜索合適的_except異常處理塊,因此向量化結(jié)構(gòu)異常處理有機(jī)會(huì)在任何_except塊之前處理異常結(jié)構(gòu)化向量異常處理鏈表是屬于整個(gè)進(jìn)程的,不管哪個(gè)線程的哪個(gè)函數(shù)發(fā)生異常都會(huì)先遍歷該鏈表,這為從全局角度處理異常提供了機(jī)會(huì)。向量化異常處理不適用于Win64平臺(tái)向量化異常處理示例Vectore
20、d Exception Handler與AddVectoredExceptionHandler類似AddVectoredContinueHandler函數(shù)添加一個(gè)繼續(xù)處理的異?;卣{(diào)過濾鏈表AddVectoredContinueHandler參數(shù)與AddVectoredExceptionHandler類似AddVectoredContinueHandler添加的函數(shù)將在某個(gè)異常未得到處理并需要繼續(xù)處理時(shí)被調(diào)用,即在所有的向量化異常處理及_except塊都沒能處理異常的情況下,開始遍歷ContinueHandler鏈表C+異常處理在C+中異常處理是語(yǔ)言語(yǔ)法的一部分使用try包含代碼保護(hù)體使用cat
21、ch塊捕捉或攔截各種異常使用throw語(yǔ)句可以顯式的拋出一個(gè)任意類型的異常catch塊一般只能捕獲由throw顯式拋出的異常(不管在什么地方拋出,只有嵌套層次中有對(duì)應(yīng)的catch即可捕獲)catch(.)可以攔截所有類型的異常包括非throw出的(VC+對(duì)catch(.)語(yǔ)法做了擴(kuò)展,使其還能捕獲SEH的異常,但其他語(yǔ)言平臺(tái)中可能不適用,即不能在其它平臺(tái)中依賴catch(.)捕獲所有異常)C+異常處理經(jīng)常用來(lái)從較深的函數(shù)調(diào)用嵌套中跳出到最外層,因此當(dāng)異常拋出點(diǎn)嵌套過深時(shí),分析程序邏輯會(huì)有一定困難C+異常處理沒有SEH的終止處理語(yǔ)法或機(jī)制,同時(shí)不能返回到發(fā)生異常處繼續(xù)執(zhí)行代碼,而只能執(zhí)行catc
22、h塊中的語(yǔ)句做有限的處理但C+異常處理語(yǔ)法簡(jiǎn)潔明了,并且是標(biāo)準(zhǔn)C+語(yǔ)法的組成部分可以方便的進(jìn)行移植混用C+異常和SEHVC+作為C+一個(gè)IDE環(huán)境本身就完全支持標(biāo)準(zhǔn)C+的異常處理同時(shí)VC+作為Windows平臺(tái)上的一個(gè)IDE本身還支持Windows平臺(tái)的SEH機(jī)制因此能夠在VC+中混用標(biāo)準(zhǔn)C+異常處理和SEH異常處理如要混用二者,必須打開項(xiàng)目的/Eha開關(guān)此開關(guān)在項(xiàng)目屬性-配置屬性-C/C+-代碼生成-啟用C+異常 選項(xiàng)中混用二者會(huì)使程序具備可以攔截所有異常的能力在混用時(shí),在一個(gè)函數(shù)體內(nèi)只能使用一種異常處理框架要么是EH要么是SEH混用EH和SEH示例如何徹底混用EH和SEH從剛才的例子中可以看
溫馨提示
- 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- T-ZRIA 002-2024 工業(yè)巡檢四足機(jī)器人通.用技術(shù)條件
- T-ZSM 0058-2024“領(lǐng)跑者”評(píng)價(jià)技術(shù)要求 飾面木質(zhì)墻板
- 二零二五年度林業(yè)林地經(jīng)營(yíng)權(quán)買賣合同
- T-ZJATA 0022-2024 土壤中揮發(fā)性有機(jī)物測(cè)定用便攜式氣相色譜-質(zhì)譜聯(lián)用儀
- T-ZJZYC 022-2024 靈芝工廠化生產(chǎn)技術(shù)規(guī)程
- 二零二五年度簽約主播與汽車廠商合作直播試駕體驗(yàn)協(xié)議
- 二零二五年度會(huì)展中心物業(yè)管理服務(wù)托管協(xié)議
- 二零二五年度新能源項(xiàng)目投資對(duì)賭協(xié)議
- 二零二五年度股東清算與清算資產(chǎn)評(píng)估及拍賣協(xié)議
- 二零二五年度創(chuàng)新創(chuàng)業(yè)團(tuán)隊(duì)員工合作協(xié)議書
- 畢業(yè)設(shè)計(jì)外文文獻(xiàn)-Spring Boot
- 六年級(jí)下冊(cè)《生命.生態(tài).安全》全冊(cè)教案(表格式)
- 采購(gòu)入庫(kù)單模板
- GB 14930.1-2022食品安全國(guó)家標(biāo)準(zhǔn)洗滌劑
- GB/T 15566.6-2007公共信息導(dǎo)向系統(tǒng)設(shè)置原則與要求第6部分:醫(yī)療場(chǎng)所
- 中國(guó)電信教育基地市級(jí)“三通兩平臺(tái)”建設(shè)方案(教育機(jī)構(gòu))
- 火力發(fā)電廠節(jié)能技術(shù)經(jīng)濟(jì)指標(biāo)釋義
- 智能制造知識(shí)課件
- 雙方責(zé)任及工程分工界面
- 2017醫(yī)學(xué)倫理知情同意書
- 中醫(yī)學(xué)-導(dǎo)論課件
評(píng)論
0/150
提交評(píng)論