SORU
14 Mart 2010, Pazar


Nasıl bir özel durum C atıldı nerede bulabilirim ?

Bir yerde yakalanmamış bir istisna atar bir program var. Ben tek bir özel durumu oluşturuldu, ve atılmış olduğu konusunda hiçbir bilgi rapor. Bir program hata ayıklama sembollerini içeren derlenmiş benim kod bir özel durum oluşturdu nerede olduğunu bana bildir, çünkü mantıksız geliyor.

Orada benim özel durumlar 'at' gdb ve her atılan özel durum için bir geri iz arıyor? yakalamak ayarı kısa nereden geldiğini anlatmak için herhangi bir yolu var mı

CEVAP
15 Mart 2010, PAZARTESİ


Burada bazı bilgilerolabilirsorun hata ayıklama işine

Eğer bir özel durum yakalanmamış ise, özel kütüphane std::terminate() fonksiyonu otomatik olarak adlandırılır. Sona aslında bir işlev için bir işaretçi alır ve varsayılan değer Standart C kütüphane fonksiyonları std::abort(). Eğer temizlikleri yakalanmamış bir istisna oluşursabunuolabiliraslında hiçbir yıkıcı olarak adlandırılan bu sorun, hata ayıklama yardımcı olabilir.
std::terminate() denir önce yığın çözülmemiş olup olmadığını tanımlı uygulama.


5* *bir ara sık sık özel durumun nedenini belirlemek için analiz edilebilir bir çekirdek dökümü oluşturmada yararlıdır. ulimit -c unlimited (Linux) çekirdek döker etkinleştirmek emin olun.


Kullanarak terminate() kendi işlevi yükleyebilirsinizstd::set_terminate(). Eğer kesme noktası gdb fonksiyonu sonlandırmak ayarlamak gerekir. Sanaolabiliryığın terminate() fonksiyon ve bu geri iz dan geri iz bir üretebilirolabiliristisna konumunu belirlemede yardımcı olur.

Yararlı olabilir Bruce Eckel's Thinking in C , 2nd Ed 23 *üzerinde kısa bir tartışma yok.


terminate() varsayılan abort() varsayılan SIGABRT bir sinyal neden olacak () çağrıları beriolabilirSIGABRT işleyicisi ayarlamak mümkün olacak ve daha sonra print a stack backtrace from within the signal handler. Bu geri izolabiliristisna konumunu belirlemede yardımcı olur.


Not:DerimolabilirC dil yapıları aracılığıyla yerel olmayan sıradan bir hata işleme kodu hata işleme ve raporlama kodu ayrı destekler çünkü. Catch bloğu olabilir, ve genellikle, farklı bir işlevi atma noktası daha/yöntem yer almaktadır. Veya yığın terminate() çağrılmadan önce açılmamış olup olmadığını tanımlı uygulama olduğunu da bana yorum olarak işaret edilmiştir (teşekkürler Dan).

Güncelleme:Birlikte set_terminate() SIGABRT için sinyal işleyicisi başka bir ile terminate() fonksiyon bir dizi içinde bir geri iz oluşturur Linux test adında bir program attım. Hem backtraces doğru işlenmeyen özel durum yerini göstermek.

Güncelleme 2:Catching uncaught exceptions within terminate, ben bir blog yazısı sayesinde birkaç yeni hileler öğrendim; yakalanmamış yeniden atma da dahil olmak üzere özel durum içinde sonlandırma işleyicisi. Özel içinde throw boş deyim GCC ile işleyici çalışır sonlandırmak dikkat etmek önemlidir ve taşınabilir bir çözüm değildir.

Kod:

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef __USE_GNU
#define __USE_GNU
#endif

#include <execinfo.h>
#include <signal.h>
#include <string.h>

#include <iostream>
#include <cstdlib>
#include <stdexcept>

void my_terminate(void);

namespace {
    // invoke set_terminate as part of global constant initialization
    static const bool SET_TERMINATE = std::set_terminate(my_terminate);
}

// This structure mirrors the one found in /usr/include/asm/ucontext.h
typedef struct _sig_ucontext {
   unsigned long     uc_flags;
   struct ucontext   *uc_link;
   stack_t           uc_stack;
   struct sigcontext uc_mcontext;
   sigset_t          uc_sigmask;
} sig_ucontext_t;

void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext) {
    sig_ucontext_t * uc = (sig_ucontext_t *)ucontext;

    // Get the address at the time the signal was raised from the EIP (x86)
    void * caller_address = (void *) uc->uc_mcontext.eip;

    std::cerr << "signal " << sig_num 
              << " (" << strsignal(sig_num) << "), address is " 
              << info->si_addr << " from " 
              << caller_address << std::endl;

    void * array[50];
    int size = backtrace(array, 50);

    std::cerr << __FUNCTION__ << " backtrace returned " 
              << size << " frames\n\n";

    // overwrite sigaction with caller's address
    array[1] = caller_address;

    char ** messages = backtrace_symbols(array, size);

    // skip first stack frame (points here)
    for (int i = 1; i < size && messages != NULL;   i) {
        std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
    }
    std::cerr << std::endl;

    free(messages);

    exit(EXIT_FAILURE);
}

void my_terminate() {
    static bool tried_throw = false;

    try {
        // try once to re-throw currently active exception
        if (!tried_throw  ) throw;
    }
    catch (const std::exception &e) {
        std::cerr << __FUNCTION__ << " caught unhandled exception. what(): "
                  << e.what() << std::endl;
    }
    catch (...) {
        std::cerr << __FUNCTION__ << " caught unknown/unhandled exception." 
                  << std::endl;
    }

    void * array[50];
    int size = backtrace(array, 50);    

    std::cerr << __FUNCTION__ << " backtrace returned " 
              << size << " frames\n\n";

    char ** messages = backtrace_symbols(array, size);

    for (int i = 0; i < size && messages != NULL;   i) {
        std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
    }
    std::cerr << std::endl;

    free(messages);

    abort();
}

int throw_exception() {
    // throw an unhandled runtime error
    throw std::runtime_error("RUNTIME ERROR!");
    return 0;
}

int foo2() {
    throw_exception();
    return 0;
}

int foo1() {
    foo2();
    return 0;
}

int main(int argc, char ** argv) {
    struct sigaction sigact;

    sigact.sa_sigaction = crit_err_hdlr;
    sigact.sa_flags = SA_RESTART | SA_SIGINFO;

    if (sigaction(SIGABRT, &sigact, (struct sigaction *)NULL) != 0) {
        std::cerr << "error setting handler for signal " << SIGABRT 
                  << " (" << strsignal(SIGABRT) << ")\n";
        exit(EXIT_FAILURE);
    }

    foo1();

    exit(EXIT_SUCCESS);
}

Çıkış:

my_terminate caught unhanded exception. what(): RUNTIME ERROR!
my_terminate backtrace returned 10 frames

[bt]: (0) ./test(my_terminate__Fv 0x1a) [0x8048e52]
[bt]: (1) /usr/lib/libstdc  -libc6.2-2.so.3 [0x40045baa]
[bt]: (2) /usr/lib/libstdc  -libc6.2-2.so.3 [0x400468e5]
[bt]: (3) /usr/lib/libstdc  -libc6.2-2.so.3(__rethrow 0xaf) [0x40046bdf]
[bt]: (4) ./test(throw_exception__Fv 0x68) [0x8049008]
[bt]: (5) ./test(foo2__Fv 0xb) [0x8049043]
[bt]: (6) ./test(foo1__Fv 0xb) [0x8049057]
[bt]: (7) ./test(main 0xc1) [0x8049121]
[bt]: (8) ./test(__libc_start_main 0x95) [0x42017589]
[bt]: (9) ./test(__eh_alloc 0x3d) [0x8048b21]

signal 6 (Aborted), address is 0x1239 from 0x42029331
crit_err_hdlr backtrace returned 13 frames

[bt]: (1) ./test(kill 0x11) [0x42029331]
[bt]: (2) ./test(abort 0x16e) [0x4202a8c2]
[bt]: (3) ./test [0x8048f9f]
[bt]: (4) /usr/lib/libstdc  -libc6.2-2.so.3 [0x40045baa]
[bt]: (5) /usr/lib/libstdc  -libc6.2-2.so.3 [0x400468e5]
[bt]: (6) /usr/lib/libstdc  -libc6.2-2.so.3(__rethrow 0xaf) [0x40046bdf]
[bt]: (7) ./test(throw_exception__Fv 0x68) [0x8049008]
[bt]: (8) ./test(foo2__Fv 0xb) [0x8049043]
[bt]: (9) ./test(foo1__Fv 0xb) [0x8049057]
[bt]: (10) ./test(main 0xc1) [0x8049121]
[bt]: (11) ./test(__libc_start_main 0x95) [0x42017589]
[bt]: (12) ./test(__eh_alloc 0x3d) [0x8048b21]

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Austin Evans

    Austin Evans

    5 AĞUSTOS 2007
  • PlayStation

    PlayStation

    16 Aralık 2005
  • SPBedition

    SPBedition

    24 HAZİRAN 2013