2009-09-15 29 views
3

如何在程序語言(如C或Perl)中執行異常處理? (我知道Perl也是OO)。在Perl中處理程序代碼中的異常的最好方法是什麼?如何處理程序語言中的異常?

+5

足夠的Perl編程是*過程編程*,但不會使它成爲程序*語言*。這是一種多範式語言。它允許OO編程,但它也借用*功能*編程語言。我認爲沒有很多工作可以做的事情就是*邏輯*編程(比如Prolog)。 「C」是程序語言,最接近的是通過練習和執行抽象數據類型方法。 – Axeman

+0

@Axeman,請參閱CPAN上的AI :: Prolog發行版​​:http://search.cpan.org/~jjore/AI-Prolog/lib/AI/Prolog.pm – friedo

回答

1

它取決於'異常處理'的含義。

某些操作系統有異常機制 - 請參閱Windows exception handling routinesLinux signal handlers(其中有些例外)。

如果您的意思是用戶代碼中的習慣用語表示錯誤,並展開堆棧清理所有分配的對象,那麼當堆棧解開(它只是回收內存)時,C代碼不會調用分配對象上的析構函數,所以在C中函數返回狀態值是正常的,並且調用代碼在返回之前需要進行任何清理。

我不太瞭解Perl,但是對於「Perl異常處理」的谷歌搜索表明它內置了與try/catch和給出「OO風格」異常處理的模塊等價的機制。

0

傳統的方法是...好...不:)

一般來說,人們只是檢查嘗試的東西后的狀態,如果出事了,他們清理,並返回一個錯誤代碼,而不是繼續。此錯誤檢查和返回傳播回落函數調用堆棧,直到它回來到某處高層在你的程序,在那裏你願意告知用戶,而不是隻返回更多的錯誤:

int try_it() { 
    if (!do_something(...)) { 
    return TRYIT_FAILURE; 
    } 
} 

void my_gui() { 
    rc = try_it() 
    if (rc == TRYIT_FAILURE) { 
    message_box("failed when trying it.", MB_ABORT|MB_RETRY); 
    } 
    ... 
} 

你也可以做這在一個大的功能,使用嵌套IFS,如果你想要的東西就像一個try ... except結構:

if (stage1()) { 
    if (stage2()) { 
     if(stage3()) { 
      printf("success!\n"); 
     } else { 
      // error handling for stage 3 
     } 
    } else { 
     // error handling for stage 2 
    } 
} else { 
    // error handling for stage 1 
} 

如果你是一個有點失常,你可以做同樣的goto的。

但是,您至少可以在C中執行實際的異常.C有兩種標準的庫調用:setjmp和longjmp。有了這些,你可以通過幾個函數調用回到預定的地方,在那裏你知道異常(跳轉)發生了。有關更多信息,請參閱Setjmp.h#exception_handling on wikipedia

看來Perl確實有辦法做到這一點,儘管它對我來說看起來很不直觀。再說,我不代碼在Perl :)

Perl FAQ Q4.8

+0

-1 Perl開發人員確實使用異常。我認爲它們在Perl等動態語言中比在java或C++等語言中更重要; –

1

在C有setjmp和跳遠踏板;實質上,setjmp()將當前上下文保存在堆棧中,longjmp()可以退回到由setjmp()保存的點。這些wikipedia條目很好地填充了細節。

7

在Perl 5中,異常處理是使用evaldie完成的。您只需評估代碼體,如果它死了,您可以檢查[email protected]的錯誤。如果你想正確地做到這一點,這並不是那麼容易,這就是爲什麼各種try/catch模塊存在的原因。您可能對Try::Tiny感興趣,它沒有依賴關係,並描述了在使用樸素eval異常處理時必須處理的所有問題。 (另請參閱Try :: Tiny的作者this blog post。)

+0

「eval」的性能處罰可能會使其對於大型系統而言過於昂貴。 – DVK

+4

@DVK,你說的是字符串評估還是塊評估?字符串eval的問題衆所周知,但使用eval的異常處理通常使用塊eval。如果您認爲block eval存在性能問題,您能否提供該問題的來源或演示? – daotoad

+2

值得一提的是,http://gist.github.com/187483。 – zoul

2

這裏是我怎麼做在Perl(例外的例子,而不使用在Try模塊之一):

use Carp; 
use English qw(-no_match_vars); 

do_something_needing_rollback_if_failed(); 
eval { 
    do_something_dangerous(); 
} or do { 
    # Exception was thrown by dangerous method 
    # Save the error: 
    my $error = $EVAL_ERROR; 

    # Try to rollback 
    eval { rollback(); } 
    or do { confess qq{Couldn't rollback: $EVAL_ERROR. Original error $error}; } 

    # Let's rethrow: 
    confess qq{Rolled back! Error was $error}; 
} 

一個Perl的異常處理更惱人的部分是它使用一個變量來存儲任何異常錯誤,並可能意外覆蓋,所以需要一些防禦性編碼。

1

在Perl中,像往常一樣,有不止一種方法來做到這一點。然而,整個開發者社區已經決定了做大部分事情的正確方式。

我正在成爲自己的粉絲Exception::Base

如果你想要一個更輕的實現,那麼就使用鯉魚。

您使用eval { ... }; if ([email protected]) { ... }構造捕獲異常。

有了Exception :: Base它提供了一種方法來爲你抽象出if ([email protected]) { ... }結構。但你仍然需要使用eval { ... }