Yerel Olmayan Çıkışlar Hakkında
Önceki XXIII. Oylum - Yerel Olmayan Çıkışlar Sonraki
Yerel Olmayan Çıkışlar Hakkında
Yerel olmayan çıkışların ne zaman faydalı olabileceğini bir örnekle açıklamaya çalışmak daha iyi olacak. Bir ana döngüyle kullanıcıdan komutları alıp bunları çalıştıran etkileşimli bir yazılımımız olduğunu varsayalım. Komutları bir dosyadaki girdilerden okuduğunu ve girdideki komutu işleme sokmadan önce bazı metin çözümleme işlemleriyle girdiyi analiz ettiğini farzedelim. Bir düşük seviyeli hata saptandığında, metin çözümleme, ayrımsama ve işleme fazlarının her yapılışında iç içe çağrılarda saptanan hatalarla yerinde uğraşmaktansa hemen ana döngüye dönebilmek iyi olurdu.
(Diğer taraftan, her fazdan çıkışta önemli miktarda temizlik işlemleri yapılması gerekli olabilir--örneğin, dosyaların kapatılması, tamponların ve veri yapılarının serbest bırakılması ve benzerleri--ancak bundan sonra normal dönüş yapmak daha uygun olabilir. Bir yerel olmayan çıkış ara fazların ve onlarla ilgili temizlik kodunun atlanmasına neden olacağından her fazın kendine özgü temizlik kodu olması da daha uygun olabilir. Bundan başka, temizliği ana döngüye dönmeden önce ya da döndükten sonra yapacak şekilde de bir yerel olmayan çıkış kullanabilirdiniz.)
Bazı bakımlardan, bir yerel olmayan çıkış, bir işlevden çıkış deyimi olan return kullanımına benzer. Fakat return sadece tek bir işlev çağrısından çıkıp denetimi geriye işlev çağrısının yapıldığı noktaya taşırken, bir yerel olmayan çıkış denetimin potansiyel olarak çok iç içe pek çok işlev çağrısının dışındaki bir noktaya taşınmasını sağlar.
Yerel olmayan çıkışlarda denetimin döndürüleceği noktayı setjmp işlevini çağırarak belirtebilirsiniz. Bu işlev, setjmp işlev çağrısının göründüğü icra ortamı hakkındaki bilgiyi jmp_buf türündeki bir nesneye kaydeder. Yazılımın çalışması setjmp çağrısından sonra normal olarak devam eder, fakat daha sonra bu dönüş noktası için kaydedilen jmp_buf türündeki nesne ile yapılan bir longjmp çağrısı ile bu dönüş noktasına bir çıkış yapılırsa, denetim setjmp çağrısının yapıldığı noktaya aktarılmış olur. setjmp çağrısından dönen değer ile sıradan bir dönüş ve longjmp çağrısı tarafından yapılan bir dönüş arasında ayrım yapılabilmesi için setjmp çağrısının bir if deyimi içinde görünmesi gerekir.
Bunun nasıl yapıldığına bir örnek:
#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>

jmp_buf main_loop;

void
abort_to_main_loop (int status)
{
  longjmp (main_loop, status);
}

int
main (void)
{
  while (1)
    if (setjmp (main_loop))
      puts ("Ana döngüye geri dönüldü....");
    else
      do_command ();
}


void
do_command (void)
{
  char buffer[128];
  if (fgets (buffer, 128, stdin) == NULL)
    abort_to_main_loop (-1);
  else
    exit (EXIT_SUCCESS);
}
abort_to_main_loop işlevi nereden çağrıldığına bakılmaksızın, denetimin, yazılımın ana döngüsüne geri dönmesine sebep olur.
main işlevinin içindeki akış denetimi başta biraz esrarlı görünebilir. Bir normal setjmp çağrısı sıfırla döner, böylece "else" sözcüğündeki kod çalışır. do_command içinde bir yerlerde abort_to_main_loop yapılırsa, hemen ardından main içinde -1 değeri döndüren ikici bir setjmp çağrısı yapılmış gibi görünür.
setjmp kullanımını genel kalıbı şöyle görünür:
if (setjmp (tampon))
  /* Erken dönüş sonrası temizleme kodu. */
  …
else
  /* Dönüş noktası ayarlandıktan sonra
     normal olarak çalıştırılacak kod. */
  …
Önceki Üst Ana Başlık Sonraki
XXIII. Oylum - Yerel Olmayan Çıkışlar Başlangıç Yerel Olmayan Çıkışların Ayrıntıları
Bir Linux Kitaplığı Sayfası