線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1223
推到 Plurk!
推到 Facebook!

关于Abort的一点疑问

尚未結案
fangwy
中階會員


發表:99
回覆:139
積分:62
註冊:2003-09-10

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-10-10 16:23:39 IP:218.5.xxx.xxx 未訂閱
我在写代码时喜欢这样处理 function a():Boolean; var i: string; j: integer; dbRet:Boolean; begin try 给i赋值; j := StrToInt(i); if j > 9 then Abort; a的其他处理 dbRet := True; except dbRet := False; end; //返回前的一些必要处理 a := dbRet; end; function b():Boolean; var dbRet:Boolean; begin try dbRet := False; if not a() then //这里a()虽然处理失败,但我仅仅是不想做后面的处理,但仍返回成功 begin dbRet := True; <---- Abort; end; b其他处理; dbRet := True; except end; //返回前的一些必要处理 b := dbRet; end; function c():Boolean; var dbRet:Boolean; begin try if not b() then begin Abort; end; c其他处理1; c其他处理2; c其他处理3; dbRet := True; except dbRet := False; end; //返回前的一些必要处理 c := dbRet; end; 这样做主要是因为我觉得处理流程清晰,不会造成很多if的嵌套,又能够处理一些异常如a()中的j := StrToInt(i)可能出现无效的数值, 还可将函数的结束处理集中到函数末尾处理.但是今天出了个怪问题: 在c()中,调用b()返回true后(是在a()处理失败的情况下返回的true,箭头指示的位置),并没有去处理'c其他处理1'而是跳到了'c其他处理3'(实际代码中甚至跳到其他分支去了(即本不应处理的else中)). 代码实在太长了无法贴上,上面举个例子,基本与我的代码处理情况一致. 我想问问先知,我这样使用Abort是否有问题;我出现的异常是否与这样的处理方式有关;如果except换成finally是否有一样的问题或有新的问题? 再说明一下,上述问题,后来自已消失了. 發表人 - fangwy 於 2004/10/10 16:28:53
change.jian
版主


發表:29
回覆:620
積分:439
註冊:2003-06-02

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-10-10 20:00:37 IP:61.229.xxx.xxx 未訂閱
hi,fangwy:    1.原則上,abort其實可以看成是raise一個exception,只不過是舉發一個沒有訊息的例外而已.    2.我想,你可能追錯程式碼了.在function c中,如果not b()的話,接著會執行的是abort,那麼,從abort到except之間的程式碼是不會被執行的,而會直接跳到except-end之間的程式碼執行,然後接著再執行function c中,返回前的一些必要处理及最後的c := dbRet;    3.我想,你可能弄錯了一個地方.如果abort有被try-except-end包住,那麼就會執行except以後的指令,如果沒有的話,那麼abort接著就是結束,不會再執行.其實,你可以試著執行以下的程式碼即可知道流程
procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    ShowMessage('1');
    abort;
    showMessage('2');
  except
    ShowMessage('error');
  end;
  ShowMessage('continue');
end;
在上例中,showMessage('2')是不會被執行到的 發表人 - change.jian 於 2004/10/10 20:12:09
fangwy
中階會員


發表:99
回覆:139
積分:62
註冊:2003-09-10

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-10-11 09:05:06 IP:218.5.xxx.xxx 未訂閱
谢谢change.jian,不过你可以没理解我的说明: if not b() then begin Abort; end; b()返回的是true,理应执行'c其他处理1;',但实际却跳到其他语句去了,完全不符合流程 其实这种问题我有遇过类似的,当时我是声明了一个string变量,然后用CopyMemory将一个Buffer的数据复制过来,如下: aaa:string bbb:buffer: array[100]of Char; CopyMemory(PChar(aaa),@buffer,100); 结果出现某些语句总是执行不到, 后来将aaa:string改成aaa:string[101];就没问题了. 但这一次没有发现类似问题,不知为何出现类似现象. 这样的问题可能没有出问题的程序码确实难以分析,我只是想知道我这样使用Abort是否安全,即会不会引起一些意想不到的问题. 發表人 - fangwy 於 2004/10/11 09:28:11
change.jian
版主


發表:29
回覆:620
積分:439
註冊:2003-06-02

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-10-11 12:23:58 IP:61.218.xxx.xxx 未訂閱
我猜你的情況應該如下:    如果你的CopyMemory(PChar(aaa),@buffer,100);這行指令是在FUNCTION B,而且沒有被try-except-end包住.那麼當CopyMemory這行指令出錯時,在function C這裡呼叫function B的這行指令就會舉發例外,這個結果會跟你的function B回傳False是一樣的情形,因為回傳False之後,接著執行abort,那當然後面的指令就不會執行了到.    我想,你的問題應該是出現在你的function最後的"返回前的處理"這裡.因為這裡沒有被try-except-end包起來,一但有出錯,那麼呼叫這個function的程式碼就會有例外被舉發.而雖然你呼叫function時,會用try-except-end包住,但因為如果回傳不是True時,你的程式也會舉發例外,所以這時會造成混淆.    你可以試著檢查看看,是否都在"返回前的處理"這段程式碼裡有錯,才造成程式的流程不是你預期的結果.    
引言: 谢谢change.jian,不过你可以没理解我的说明: if not b() then begin Abort; end; b()返回的是true,理应执行'c其他处理1;',但实际却跳到其他语句去了,完全不符合流程 其实这种问题我有遇过类似的,当时我是声明了一个string变量,然后用CopyMemory将一个Buffer的数据复制过来,如下: aaa:string bbb:buffer: array[100]of Char; CopyMemory(PChar(aaa),@buffer,100); 结果出现某些语句总是执行不到, 后来将aaa:string改成aaa:string[101];就没问题了. 但这一次没有发现类似问题,不知为何出现类似现象. 这样的问题可能没有出问题的程序码确实难以分析,我只是想知道我这样使用Abort是否安全,即会不会引起一些意想不到的问题. 發表人 - fangwy 於 2004/10/11 09:28:11
fangwy
中階會員


發表:99
回覆:139
積分:62
註冊:2003-09-10

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-10-11 14:12:33 IP:218.5.xxx.xxx 未訂閱
谢谢change.jian的耐心分析,因代码太长了,只好写一些抽象的实例,可能没表达的得清楚: CopyMemory(PChar(aaa),@buffer,100)不在这一次的代码中,我只是说以前使用CopyMemory(PChar(aaa),@buffer,100)时有出过类似错误,而且也与 try...except...end结构无关,因为当时的情况是莫名其妙的跳过一行代码,例如代码的流程如下(代码1-4分别代表代码中的一行): 代码1; 代码2; diSeq := 0; 代码3; 代码4; . . . 执行完'代码2'直接跳到了'代码3'执行,把'diSeq := 0'给略了.我设了断点,按F8一步步执行,清楚的看到'diSeq:=0'被跳过了. 再次说明,这里只是描述以前出错的情况,与这一次的情况不同但错误现象类似. 另外'返回前的处理'中我一般做些简单的处理,如给传值型参数赋值以返回相关数据,如果有出错可能的处理,我还是会考虑将其放在try...except...end中. 發表人 - fangwy 於 2004/10/11 14:21:17
change.jian
版主


發表:29
回覆:620
積分:439
註冊:2003-06-02

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-10-11 16:20:51 IP:61.218.xxx.xxx 未訂閱
1.如果diSeq這個變數只在這一行出現,那麼Dephi會不執行是正常的,因為diSeq給不給值對執行結果沒有影響.    2.如果後面還會對diSeq去做處理,那麼我就不曉得為什麼你的程式碼會突然莫名的跳過某一行.老實說,我還沒碰過,如果有,那真是Delphi很大的一個bug了.    3.因為沒有看到你實際的程式碼,實在沒有辦法去找到原因(如果原因真的不簡單的話),看有沒有其他大大有這樣的經驗可以提供了 <>< face="Verdana, Arial, Helvetica">引言: 谢谢change.jian的耐心分析,因代码太长了,只好写一些抽象的实例,可能没表达的得清楚: CopyMemory(PChar(aaa),@buffer,100)不在这一次的代码中,我只是说以前使用CopyMemory(PChar(aaa),@buffer,100)时有出过类似错误,而且也与 try...except...end结构无关,因为当时的情况是莫名其妙的跳过一行代码,例如代码的流程如下(代码1-4分别代表代码中的一行): 代码1; 代码2; diSeq := 0; 代码3; 代码4; . . . 执行完'代码2'直接跳到了'代码3'执行,把'diSeq := 0'给略了.我设了断点,按F8一步步执行,清楚的看到'diSeq:=0'被跳过了. 再次说明,这里只是描述以前出错的情况,与这一次的情况不同但错误现象类似. 另外'返回前的处理'中我一般做些简单的处理,如给传值型参数赋值以返回相关数据,如果有出错可能的处理,我还是会考虑将其放在try...except...end中. 發表人 - fangwy 於 2004/10/11 14:21:17
fangwy
中階會員


發表:99
回覆:139
積分:62
註冊:2003-09-10

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-10-12 11:08:54 IP:218.5.xxx.xxx 未訂閱
这种怪现象我自已认为可能是内存处理的问题,如:用CopyMemory不当,造成数组越界了,因内存处理的这种问题一旦存在,什么样的怪问题都遇到过. 因为目前工作涉及大量对内存缓冲区的处理,以前的工作没有这方面的运用所以也没遇到这些问题. 经过与change.jian的探讨,我感觉,我在函数中用try...except...end和Abort来控制流程应该不会有问题,我的目的达到了,谢谢change.jian
系統時間:2024-05-17 13:27:10
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!