關於錯誤訊息及Exception的處理? |
尚未結案
|
nlj859
資深會員 發表:139 回覆:375 積分:322 註冊:2004-03-20 發送簡訊給我 |
我的程式碼如下:
有時會在紅字那行出現錯誤.
Times=0; void __fastcall TForm1::Timer1Timer(TObject *Sender) { try { if ((Now().FormatString("ss"))%60==0) { Timer1->Enabled=false; _di_IGEDGatewayToClient abc; HTTPRIO1->QueryInterface(abc); abc->Send(Times); Times++; Timer1->Enabled=true; } } catch(...) { Memo1->Lines->Add("............."); Memo1->Lines->Add("Error...Retry..."); abc->Send(Times); } }0.因為不曉得會有什麼exception,所以使用catch(...) 1.請問該如讓出現錯誤的那行繼續執行一次,直到他成功為止? 2.上面藍色那行,如何順便顯示錯誤訊息於Memo1上? 3.不讓錯誤時中斷程式執行,一定要將設定Tools->Debugger Options->Language Exceptions下方「Stop on Delphi Exceptions」、「Stop on C++ Exceptions」這兩項的打勾給取消嗎? 4.上面程式紅字出現的錯誤訊息如下: 5.於出現錯誤的那行裡使用了try catch,但是錯誤情況一樣發生,程式一樣中斷,請問我該如何修改才正確? 謝謝. 發表人 - nlj859 於 2004/09/05 16:13:34 |
seeing
初階會員 發表:49 回覆:131 積分:41 註冊:2002-11-07 發送簡訊給我 |
|
nlj859
資深會員 發表:139 回覆:375 積分:322 註冊:2004-03-20 發送簡訊給我 |
|
bigdogchina
版主 發表:238 回覆:523 積分:312 註冊:2003-04-28 發送簡訊給我 |
不好意思,插個花:
小弟的一點淺見,還請各位批評:
先來看一個C的例子:
#include上面的程式中,如果fopen()函數返回了NULL值,那麽就可以認爲打開文件的操作失敗了。這是C中通常的做法,但是這樣有幾點不太好:首先,一個健壯的程式要考慮許多會使程式失敗的因素,如果對每個因素都進行如上面那樣的條件判斷,那麽整個程式的結構必然變得很混亂。其次,可能函數的所有返回值都是合法的,從而找不到一個表示錯誤的方法。最後,有些函數可能根本就不返回任何值(C 中的構造函數和析構函數) 那我們是不是找另外一種處理錯誤的方法,它應該有以下幾個特定: ⑴不要打亂程式的結構,如果沒有任何錯誤産生,那麽程式的運行將不受任何影響 ⑵不依靠函數的返回值來報告錯誤是否産生 ⑶即使採用集中的方式處理錯誤,也能夠根據錯誤種類的不同來進行錯誤處理操作 具體的來看看C (當然包含BCB和一切符合C 標準的編譯器哦)將怎樣做到以下幾點: #include可見我們將所有可能産生異常的語句包含在try塊中,並在隨之而來的catch語句總捕獲發生的異常。一個try快後可以跟隨幾個不同的catch語句,用來捕獲不同的異常。如果希望捕獲任何可能發生的異常,應該使用catch(...)語句。如果我們希望在封裝成一個自己的異常類,則: class Out(); int main(int argc, char* argv[]) { try { throw Out(); //抛出一個臨時的Out物件 } catch(Out & e) //捕獲Out異常 { cout<<"Out的異常已被捕獲"<利用關鍵字throw可以抛出任意的物件,這個物件不需要繼承exception類。即使是基本資料類型,也可以作爲throw的參數而被抛出。在catch的參數中如果包含一個變數聲明的運算式,就可以在catch塊中使用這個異常類。如果在catch塊中處理完一個異常類之後,異常造成的後果並不能完全消除,那麽可以在catch語句中再次調用catch語句,從而使得捕獲的異常向外層傳播。如果在一個函數中沒有處理發生的異常,那麽異常將會傳播到調用此函數的代碼段中. 您還可以參考小弟在下面這篇中的討論: http://delphi.ktop.com.tw/topic.php?TOPIC_ID=53541 參考文獻:"C Primer" ================================= 人生在勤,不索何獲 業精於勤荒於嬉,行成於思毀於隨 臨淵羡魚不如退而結網
------
人生在勤,不索何获? |
pwipwi
版主 發表:68 回覆:629 積分:349 註冊:2004-04-08 發送簡訊給我 |
|
andychang1690
資深會員 發表:20 回覆:694 積分:442 註冊:2003-03-14 發送簡訊給我 |
|
nlj859
資深會員 發表:139 回覆:375 積分:322 註冊:2004-03-20 發送簡訊給我 |
|
andychang1690
資深會員 發表:20 回覆:694 積分:442 註冊:2003-03-14 發送簡訊給我 |
nlj859:對不起我使用BCB5並沒有WebServices組件,但請試試以下方式可否 攔截到錯誤訊息,再行處理OK! 試試於.hpp檔加入 public: // User declarations __fastcall TFormMain(TComponent* Owner); void __fastcall HandleExceptions(TObject *Sender, Exception *E); .cpp檔 void __fastcall TFormMain::FormCreate(TObject *Sender) { // 設定exception handler.自定義異常處理窗口 Application->OnException = HandleExceptions; } void __fastcall TFormMain::HandleExceptions(TObject *Sender, Exception *E) { if (E->Message.Length()) { Screen->Cursor = crArrow; AnsiString errorstr="應用程序發生了錯誤.\n" E->Message; Application->MessageBox(errorstr.c_str(),"發生異常",MB_OK); } } 請參考。Andy Chang
------
Andy Chang |
powerhowardchen
初階會員 發表:15 回覆:28 積分:28 註冊:2004-04-19 發送簡訊給我 |
用 SetErrorMode(SEM_FAILCRITICALERRORS); 吧! (加在主程式的開頭)
這樣, 所有的錯誤訊息就都會被導到Exception物件, 就不會再有錯誤訊息出現了. 其實, 我覺得 Exception 滿好用的, 既可用來分類錯誤類型, 以及自訂錯誤類型, 又可攜帶錯誤的原因、相關物件、數值、資料等, 他可以簡化程式設計的複雜度, 能容易的跳離後續處理的程式, 不必再寫一大堆的錯誤判斷式, 更不再需要將錯誤情形與錯誤碼分別傳回(所以 Windows 才用 GetLastError(), 因為Windows不能預期使用API的程式能不能接收Exception); 我個人認為, Indy的做法很好, 讓我可以很清楚的知道錯誤原因, 至於要不要略掉或是要處理錯誤, 就都在於我囉. ==================================================
Howard Chen.
Delphi, Java 我的神.....
.NET 垃圾筒在哪裡?...
|
nlj859
資深會員 發表:139 回覆:375 積分:322 註冊:2004-03-20 發送簡訊給我 |
引言:請問該如何去處理攔截到的訊息? 可否舉例一下? 謝謝.nlj859:對不起我使用BCB5並沒有WebServices組件,但請試試以下方式可否 攔截到錯誤訊息,再行處理OK! 試試於.hpp檔加入 public: // User declarations __fastcall TFormMain(TComponent* Owner); void __fastcall HandleExceptions(TObject *Sender, Exception *E); .cpp檔 void __fastcall TFormMain::FormCreate(TObject *Sender) { // 設定exception handler.自定義異常處理窗口 Application->OnException = HandleExceptions; } void __fastcall TFormMain::HandleExceptions(TObject *Sender, Exception *E) { if (E->Message.Length()) { Screen->Cursor = crArrow; AnsiString errorstr="應用程序發生了錯誤.\n" E->Message; Application->MessageBox(errorstr.c_str(),"發生異常",MB_OK); } } 請參考。Andy Chang |
nlj859
資深會員 發表:139 回覆:375 積分:322 註冊:2004-03-20 發送簡訊給我 |
引言: 用 SetErrorMode(SEM_FAILCRITICALERRORS); 吧! (加在主程式的開頭) 這樣, 所有的錯誤訊息就都會被導到Exception物件, 就不會再有錯誤訊息出現了. 其實, 我覺得 Exception 滿好用的, 既可用來分類錯誤類型, 以及自訂錯誤類型, 又可攜帶錯誤的原因、相關物件、數值、資料等, 他可以簡化程式設計的複雜度, 能容易的跳離後續處理的程式, 不必再寫一大堆的錯誤判斷式, 更不再需要將錯誤情形與錯誤碼分別傳回(所以 Windows 才用 GetLastError(), 因為Windows不能預期使用API的程式能不能接收Exception); 我個人認為, Indy的做法很好, 讓我可以很清楚的知道錯誤原因, 至於要不要略掉或是要處理錯誤, 就都在於我囉. ================================================== Howard Chen. Delphi, Java 我的神..... .NET 垃圾筒在哪裡?...請問可否舉例一下使用方法呢? 謝謝. |
powerhowardchen
初階會員 發表:15 回覆:28 積分:28 註冊:2004-04-19 發送簡訊給我 |
從你ㄧ開始問的問題回答.... > 0.因為不曉得會有什麼exception,所以使用catch(...) A: 要攔截 Exception , 可以用 catch(Exception &e), 就幾乎都可以欄到了, 而 e 就是丟出的錯誤訊息物件.
> 1.請問該如讓出現錯誤的那行繼續執行一次,直到他成功為止? A: 可以做一個循環判斷程式, 請參考範例. > 2.上面藍色那行,如何順便顯示錯誤訊息於Memo1上? A: 從問題 0 的作法中, 取得的 e 物件就會有錯誤訊息內容, 可以在 catch 內用 Memo1->Lines->Add(e.ClassName() ":" e.Message); 即可.
我喜歡將 ClassName() 顯示出來, 這樣我就很容易可以知道 Excpetion 的類型, 方便我在改程式時, 加上 Exception 類型的判斷處理. > 3.不讓錯誤時中斷程式執行,一定要將設定Tools->Debugger Options->Language Exceptions下方「Stop on Delphi Exceptions」、「Stop on C Exceptions」這兩項的打勾給取消嗎? A: 你也可以設定 "Exception Types to Ignore", 當取得了 Excpetion 的物件類型後, 將該類型加入 Ignore 清單中即可.
通常, 我是都將該項目打勾, 讓錯誤都 Ignore 掉, 等到有錯誤訊息被發現時, 才開起來做偵錯.
原本 Delphi 2 版中, 對於程式中已經被程式所攔截的 Exception 都會直接被 Ignore 而不會讓 Delphi 顯示, 可是 Delphi 3 起就都會被顯示了, 我認為這樣是好的, 因為當 Exception 被觸發(raise 或是 throw)時, 要讓 Debug 程式(Delphi) 去判斷該程式會不會在"未來"去攔截此一 Exception, 是很容易出錯的. > 4.上面程式紅字出現的錯誤訊息如下: A: 這是 BCB 攔截錯誤後所顯示的訊息. 就看你要不要採用問題 3 的作法囉. > 5.於出現錯誤的那行裡使用了try catch,但是錯誤情況一樣發生,程式一樣中斷,請問我該如何修改才正確? A: 你可以把 SetErrorMode(SEM_FAILCRITICALERRORS); 這行寫在這個函式的剛開始的位置(要在try之前), 這樣系統就只會把錯誤訊息網你這兒送, 不會自己Show出來.
用 SetErrorMode 只是避免 Windows(OS) 自己去顯示錯誤而不讓該程式去攔截(像是軟碟片沒插入, 磁碟機異常等), 但是你在問題 4 的情況則是正常的, 就看你要不要設定罷了. ==================================================
Howard Chen.
Delphi, Java 我的神.....
.NET 垃圾筒在哪裡?...
|
powerhowardchen
初階會員 發表:15 回覆:28 積分:28 註冊:2004-04-19 發送簡訊給我 |
範例: // SendData 是你要傳送的資料, TimeOutMS 是總共容許傳送的時間(千分之ㄧ秒 ms)
void __fastcall TForm1::AdvSend(void *SendData, DWORD TimeOutMS)
{
DWORD BeginTick = GetTickCount();
String ErrorMsg;
SetErrorMode(SEM_FAILCRITICALERRORS);
while (GetTickCount() - BeginTick < TimeOutMS)
{
ErrorMsg = "";
try
{
abc->Send(*SendData);
break;
}
catch(Exception &e)
{
ErrorMsg = e.ClassName() ":" e.Message;
}
}
if (ErrorMsg != "")
throw Exception(ErrorMsg);
} void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
try
{
if ((Now().FormatString("ss"))`==0)
{
Timer1->Enabled=false;
AdvSend(&Times, 10000);
Times ;
Timer1->Enabled=true;
}
}
catch(Exception &e)
{
Memo1->Lines->Add("Send fail. Error Detail: " e.Message);
}
} ==================================================
Howard Chen.
Delphi, Java 我的神.....
.NET 垃圾筒在哪裡?...
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |