Köken Arama Listeleri
Önceki XXXIII. Oylum - Hata Ayıklama Desteği Sonraki
Köken Arama Listeleri
Bir köken arama listesi (backtrace), bir evre içindeki o an etkin olan işlev çağrılarının bir listesidir. Bir yazılımın köken arama listesini elde etmenin en uygun yolu gdb gibi harici bir hata ayıklayıcı kullanmaktır. Ancak, kimi zaman bir köken arama listesini günlük tutma, tanı koyma gibi amaçlarla yazılım içinde kodlayarak elde etmek de gerekebilir.
Geçerli evrenin köken arama listesini elde eden ve onunla çalışan üç işlev vardır ve bunlar execinfo.h başlık dosyasında bildirilmiştir.
int backtrace
(void **tampon,
 int    boyut)
işlev
backtrace işlevi o anki evrenin köken arama listesini elde eder ve bir liste göstericisi olarak tampon içine yerleştirir. boyut argümanı tampon içinde bulunacak void * türündeki elemanların sayısı olmalıdır. İşlev tampon içine konmuş olan listenin eleman sayısı ile döner.
tampon içine yerleştirilen göstericiler aslında araştırılan yığıttan edinilen dönüş adresleridir, yani her yığıt çerçevesi için bir dönüş adresi vardır.
Belli derleyici eniyilemelerinin edinilen bir geçerli köken arama listesi ile etkileşeceğini gözardı etmemelisiniz. Satıriçine alma işlemi satıriçi işlevlerin bir yığıt çerçevesine sahip olmamasına sebep olur; uç çağrı eniyilemesi bir yığıt çerçevesini bir diğeri ile değiştirir; çerçeve göstericisi elemesi yığıt içeriğinin backtrace tarafından doğru olarak yorumlanmasının engelleyecektir.
char **backtrace_symbols
(void *const *tampon,
 int          boyut)
işlev
backtrace_symbols işlevi backtrace işleviyle edinilen listeyi bir dizge dizisine dönüştürür. tampon argümanı backtrace işleviyle elde edilen adres dizisinin göstericisi, boyut ise bu dizinin eleman sayısı (backtrace işlevinin dönüş değeri) olmalıdır.
İşlevin dönüş değeri boyut dizgelik dizge dizisine bir göstericidir. Her dizge tampon içindeki her elemanın basılabilir içeriğini gösterir. Saptanabiliyorsa işlev ismi, işleve bir başlangıç konumu ve geçerli dönüş adresini (onaltılık tabanda) içerir.
Şimdilik işlev ismi ve başlangıç konumu sadece kütüphaneler ve uygulamalar için ELF ikilik biçimi kullanılan sistemlerde elde edilebilmektedir. Diğer sistemlerde ise sadece onaltılık tabandaki dönüş adresi elde edilebilmektedir. Ayrıca, yazılımın işlev isimlerini içermesi için ilintileyiciye ek seçenekler belirtilebilir. (Örneğin, GNU ld'ye --rdynamic seçeneğini aktarabilirsiniz.)
backtrace_symbols işlevinin dönüş değeri malloc işlevi üzerinden edinilen ve free ile serbest bırakılması gereken bir göstericidir. Yalnız, sadece dönüş değeri serbest bırakılmalı, içerdiği dizgeler serbest bırakılmamalıdır.
Edinilen dizgeleri saklamak için bellek yetersizse işlev NULL ile döner.
void backtrace_symbols_fd
(void *const *tampon,
 int          boyut,
 int          dosyatanıtıcı)
işlev
backtrace_symbols_fd işlevi backtrace_symbols işlevinin yaptığı dönüşümün aynısını yapar, ancak farklı olarak, dizgelere bir gösterici döndürmek yerine her dizge bir satır olmak üzere dizgeleri dosyatanıtıcı tanıtıcısına yazar. malloc işlevini kullanmaz ve dosya tanıtıcılara yazan işlevlerin başarısız olmasına sebep olan durumlarda bu işlev de başarısız olabilir.
Aşağıdaki yazılımda bu işlevlerin kullanımı gösterilmiştir. backtrace tarafından döndürülen gösterici dizisinin adresinin yığıt üzerine ayrıldığına dikkat edin. Bu bakımdan, bu kod malloc üzerinden bellek ayrılamayan sistemlerde kullanılabilir (bu gibi durumlarda backtrace_symbols yerine backtrace_symbols_fd işlevi de kullanılabilir). Dönüş adreslerinin sayısı normalde çok fazla olmayacaktır. Nadiren diyelim ki 50'den fazla iç içelik içeren çok karmaşık yazılımlarda bile 200 girdi olabilir.
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

/* Köken arama listesini edinip stdout'a basalım. */
void
print_trace (void)
{
  void *array[10];
  size_t size;
  char **strings;
  size_t i;

  size = backtrace (array, 10);
  strings = backtrace_symbols (array, size);

  printf ("%zd yığıt çerçevesi elde edildi.\n", size);

  for (i = 0; i < size; i++)
      printf ("%s\n", strings[i]);

  free (strings);
}

/* Köken arama listesini biraz daha ilginç hale getirmek
   için (iç içelik olsun diye) bir işlev. */
void
dummy_function (void)
{
  print_trace ();
}

int
main (void)
{
  dummy_function ();
  return 0;
}
Önceki Üst Ana Başlık Sonraki
XXXIII. Oylum - Hata Ayıklama Desteği Başlangıç Ek A. Kütüphanedeki C Dili Oluşumları
Bir Linux Kitaplığı Sayfası