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

呼叫abort後,在退出程式時有時會顯示記憶體存取衝突之錯誤錯誤?

答題得分者是:aftcast
ry_lee
高階會員


發表:367
回覆:251
積分:123
註冊:2002-03-19

發送簡訊給我
#1 引用回覆 回覆 發表時間:2010-12-29 21:59:52 IP:111.253.xxx.xxx 未訂閱
在某條件成立時呼叫Abort或Exit以中段程式執行流程,但如在下列情況可能非用abort不可,如在某程式區塊之code中當第一函數檢查條件成立時,即不呼叫第二函數及其後程式碼

procedure TfrmMain.Button5Click(Sender: TObject);
begin
fun1;
fun2;
showmessage('check success');
end;

fun1之code:
if 條件符合時 then
exit;
那麼會接著呼叫fun2及showmessage('check success');

但如果fun1之code:
if 條件符合時 then
abort;
那麼之後fun2,及showmessage('check success');皆不執行
當我在測試程式(是以abort;來中斷流程),可少寫很多程式碼,但在退出程式偶而會發生這錯誤訊息

"錯誤訊息 access violation at address 004037EC in module ' project1.exe'. Read of address FFFFFFFD"

請問是否是呼叫 abort 之關係?是否改為呼叫 exit 較不會發生這問題?
編輯記錄
ry_lee 重新編輯於 2010-12-29 07:14:44, 註解 無‧
ry_lee 重新編輯於 2010-12-29 07:24:17, 註解 無‧
smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-12-29 23:53:38 IP:203.73.xxx.xxx 訂閱
這樣的程式邏輯不是很怪嗎?
既然都使用 function 了, 為何不寫成:

procedure TfrmMain.Button5Click(Sender: TObject);
begin
if (fun1=True) then begin
fun2;
showmessage('check success');
end;
end;

為何要在 fun1 內使用 Abort or Exit 來決定是否執行 func2 & 以下的程式碼呢?

(要走到目的地的首要方法就是.....要走對的方向)


smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-12-29 23:58:48 IP:203.73.xxx.xxx 訂閱
我的經驗是:

Abort 應使用在 "事件" 類的程序內較不會出錯, 而非使用在 function 內.
GrandRURU
站務副站長


發表:234
回覆:1651
積分:1742
註冊:2005-06-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2010-12-30 01:40:30 IP:111.249.xxx.xxx 訂閱
所以的確是Abort的問題??

因為有些function底下仍是要做DataSet的工作,有時會需要在function內做abort處理,我也常遇到記憶體存取錯誤的怪問題,明明該釋放的都釋放了

Abort,真的會是它的問題嗎???

===================引 用 smallfox 文 章===================
我的經驗是:

Abort 應使用在 "事件" 類的程序內較不會出錯, 而非使用在 function 內.
ry_lee
高階會員


發表:367
回覆:251
積分:123
註冊:2002-03-19

發送簡訊給我
#5 引用回覆 回覆 發表時間:2010-12-30 10:15:43 IP:111.253.xxx.xxx 未訂閱
謝謝 smallfox  ,GrandRURU先進寶貴的回覆,fun1,fun2其實是procedure,當然改成fun也可以,fun1之內容只是很簡單的code如下:

if edit1.text='' or edit2.text='' then
begin
showmessage('欄位不能是空白');
abort;
end;

只是以前許多程式都會用到abort也不曾出現過什麼問題,現在怎麼會出現這問題,不曉得是程式或硬體之問題,因為以前是在pc上run,現在是在NB上run?

===================引 用 GrandRURU 文 章===================
所以的確是Abort的問題??

因為有些function底下仍是要做DataSet的工作,有時會需要在function內做abort處理,我也常遇到記憶體存取錯誤的怪問題,明明該釋放的都釋放了

Abort,真的會是它的問題嗎???

===================引 用 smallfox 文 章===================
我的經驗是:

Abort 應使用在 "事件" 類的程序內較不會出錯, 而非使用在 function 內.
GrandRURU
站務副站長


發表:234
回覆:1651
積分:1742
註冊:2005-06-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-12-30 11:19:06 IP:203.75.xxx.xxx 訂閱
不知道把CodeGuard開啟後是否能抓到這類的error

===================引 用 ry_lee 文 章===================
謝謝 smallfox ,GrandRURU先進寶貴的回覆,fun1,fun2其實是procedure,當然改成fun也可以,fun1之內容只是很簡單的code如下:

if edit1.text='' or edit2.text='' then
begin
showmessage('欄位不能是空白');
abort;
end;

只是以前許多程式都會用到abort也不曾出現過什麼問題,現在怎麼會出現這問題,不曉得是程式或硬體之問題,因為以前是在pc上run,現在是在NB上run?
RootKit
資深會員


發表:16
回覆:357
積分:419
註冊:2008-01-02

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-12-30 20:54:25 IP:122.126.xxx.xxx 訂閱
通常會有這樣的問題,可能是因 Abort 會造成 事件或父元件(Form)因釋放時,指向無效的位址。
使用 Abort 要嚴謹的,因為中斷的事後所有復原的程序。有可能這些動作是隱藏在 VCL 內,既使您本身用的都有釋放掉。

絕對的建議您使用 Exit 取代 Abort 利用 Fun 回傳成功或失敗來過濾,才是嚴謹的程式碼。
GrandRURU
站務副站長


發表:234
回覆:1651
積分:1742
註冊:2005-06-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-12-31 08:44:10 IP:125.230.xxx.xxx 訂閱
我只是不想讓例外訊息跳出而已
而我的程式碼看起來像是這樣:
[code cpp]
事件或函式()
{
......
try{
try{
}
catch(...){
Abort();
}
......
}
__finally{
}
return 0;
}
[/code]

這樣不算嚴謹……嗎?

===================引 用 RootKit 文 章===================
通常會有這樣的問題,可能是因 Abort 會造成 事件或父元件(Form)因釋放時,指向無效的位址。
使用 Abort 要嚴謹的,因為中斷的事後所有復原的程序。有可能這些動作是隱藏在 VCL 內,既使您本身用的都有釋放掉。

絕對的建議您使用 Exit 取代 Abort 利用 Fun 回傳成功或失敗來過濾,才是嚴謹的程式碼。
RootKit
資深會員


發表:16
回覆:357
積分:419
註冊:2008-01-02

發送簡訊給我
#9 引用回覆 回覆 發表時間:2010-12-31 10:54:48 IP:60.250.xxx.xxx 訂閱
OK .  對函數這個區段而言是沒有問題的並且毫無疑問。

但是往往有時是,某各物件觸發某個事件執行 -> FunA -> FunB ......
使用 Abort 會中斷堆疊的遞回,包含物件的事件。

當開發專案到一定的複雜度,物件的觸發在觸發使用 Abort 的後遺症就會約來越多(程式退出 Access Viol...)。
這樣對程式碼也不好分析。

個人一點淺見。



aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#10 引用回覆 回覆 發表時間:2010-12-31 16:18:25 IP:220.135.xxx.xxx 訂閱
個人覺得,依照樓主想達成的目的,真的不應該使用Abort。建議你還是照rootkit的說法來寫程式。

要知道,Abort它真正的意函是「中斷並產生一個例外處理」,換句話說,你該去處理這個例外處理函式。你應該配套 try except (<layer id="google-toolbar-hilite-0" ><layer id="google-toolbar-hilite-0">delphi</layer></layer>語法),在except 中使用on E: Exception do …來做你想要的事。如果不想在這裡寫,那也要在TApplication::HandleException裡來處理。

GrandRuRu,在c 裡,在catch(…)中,只要空白,什麼也沒寫…就可以達到好像什麼都沒發生,而不是用Abort,否則它會在產生一次異常。

如果說,樓主只是想"偷懶"少寫,那<layer id="google-toolbar-hilite-7">exit</layer>絕對夠用了! 而不是到處產生exception,然後又完全不理會它! 不是嗎?

另外,這題目原來的問題是否和abort有關? 我覺得不盡然,可參考它的原始碼…其實很乾淨! 就是產生一個例外於呼叫者的位址上。至於為何你會發生av的現象? 是否和你「不當的,或說粗爆的就跳離函式,而不做任何的資源檢視有關」? 無論是<layer id="google-toolbar-hilite-8">exit</layer> 或是abort,都應該要注意是否該處理的,該放的,該設定值的…等等等的問題都確認後才<layer id="google-toolbar-hilite-9">exit</layer>。

當然,如果說真的是abort造成了問題(個人覺得機率很低)… 我個人覺得就是… 若真要用它,就請處理它產生的exception,不然就不要用! 這樣會好很多…

剛突然想到…問題極可能是…你沒有自己寫相對的例外處理,而可能導致它上層的某元件之類的接到,做了該元件認為要處理的例外處理,而事實上這個例外並非是該元件產生,而是你自己產生出來的,所以就亂指一通…產生了AV。例外處理是會往上層一直轉,直到有對到例外處理。所以啦,這個Abort還是不會亂用的好,除非自己去handle,而不是座視不管讓它往上轉到不該轉的地方做了例外處理。我認為你原來的實做,不單純只是showmessage,一定是有許多的元件的操作,所以亂了!


Abort的函式實作如下: 請參考一下
procedure Abort;

function ReturnAddr: Pointer;
asm
MOV EAX,[EBP 4]
end;

begin
raise EAbort.Create(SOperationAborted) at ReturnAddr;
end;
------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2010-12-31 01:29:37, 註解 無‧
ry_lee
高階會員


發表:367
回覆:251
積分:123
註冊:2002-03-19

發送簡訊給我
#11 引用回覆 回覆 發表時間:2010-12-31 20:22:29 IP:111.253.xxx.xxx 未訂閱
affcast你好:
我的程式中有TApplication::HandleException,而fun1的code真的如下簡單,
if edit1.text='' or edit2.text='' then
begin
showmessage('欄位不能是空白');
abort;
end;

因為不想在許多button及mainmenu之"'' or edit2.text='' then
begin
showmessage('欄位不能是空白');
exit;
end;
所以才會寫fun1,不過聽你及其他先進的說法,我覺得很有道理,會盡可能不用abort,改用exit.

===================引 用 aftcast 文 章===================
個人覺得,依照樓主想達成的目的,真的不應該使用Abort。建議你還是照rootkit的說法來寫程式。

要知道,Abort它真正的意函是「中斷並產生一個例外處理」,換句話說,你該去處理這個例外處理函式。你應該配套 try except (<layer id="google-toolbar-hilite-0" ></layer><layer id="google-toolbar-hilite-0" ></layer>delphi語法),在except 中使用on E: Exception do …來做你想要的事。如果不想在這裡寫,那也要在TApplication::HandleException裡來處理。

GrandRuRu,在c 裡,在catch(…)中,只要空白,什麼也沒寫…就可以達到好像什麼都沒發生,而不是用Abort,否則它會在產生一次異常。

如果說,樓主只是想"偷懶"少寫,那<layer id="google-toolbar-hilite-7" ></layer>exit絕對夠用了! 而不是到處產生exception,然後又完全不理會它! 不是嗎?

另外,這題目原來的問題是否和abort有關? 我覺得不盡然,可參考它的原始碼…其實很乾淨! 就是產生一個例外於呼叫者的位址上。至於為何你會發生av的現象? 是否和你「不當的,或說粗爆的就跳離函式,而不做任何的資源檢視有關」? 無論是<layer id="google-toolbar-hilite-8" ></layer>exit 或是abort,都應該要注意是否該處理的,該放的,該設定值的…等等等的問題都確認後才<layer id="google-toolbar-hilite-9" ></layer>exit。

當然,如果說真的是abort造成了問題(個人覺得機率很低)… 我個人覺得就是… 若真要用它,就請處理它產生的exception,不然就不要用! 這樣會好很多…

剛突然想到…問題極可能是…你沒有自己寫相對的例外處理,而可能導致它上層的某元件之類的接到,做了該元件認為要處理的例外處理,而事實上這個例外並非是該元件產生,而是你自己產生出來的,所以就亂指一通…產生了AV。例外處理是會往上層一直轉,直到有對到例外處理。所以啦,這個Abort還是不會亂用的好,除非自己去handle,而不是座視不管讓它往上轉到不該轉的地方做了例外處理。我認為你原來的實做,不單純只是showmessage,一定是有許多的元件的操作,所以亂了!


Abort的函式實作如下: 請參考一下
procedure Abort;

function ReturnAddr: Pointer;
asm
MOV EAX,[EBP 4]
end;

begin
raise EAbort.Create(SOperationAborted) at ReturnAddr;
end;

編輯記錄
ry_lee 重新編輯於 2010-12-31 05:25:13, 註解 無‧
ry_lee 重新編輯於 2010-12-31 05:26:21, 註解 無‧
系統時間:2017-10-20 5:47:57
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!