সি ++ এ যেখানে ব্যতিক্রম ছুঁড়েছে সেখানে আমি কীভাবে খুঁজে পাব?


97

আমার একটি প্রোগ্রাম রয়েছে যা কোথাও একটি অপ্রয়োজনীয় ব্যতিক্রম ছুঁড়ে ফেলেছে। আমি যা পাই তা হ'ল একটি ব্যতিক্রম নিক্ষেপের একটি প্রতিবেদন এবং এটি কোথায় ছুঁড়েছিল সে সম্পর্কে কোনও তথ্য নেই। আমার কোডটিতে একটি ব্যতিক্রম কোথায় উত্পন্ন হয়েছিল তা সম্পর্কে আমাকে অবহিত না করার জন্য কোনও প্রোগ্রামটি সংকলিত ডিবাগ প্রতীক ধারণ করে এমনটি অযৌক্তিক বলে মনে হয়।

আমার ব্যতিক্রমগুলি জিডিবিতে 'ক্যাচ থ্রো' সেট করার সংক্ষিপ্ত থেকে এবং প্রতিটি একক ছোঁড়া ব্যতিক্রমের জন্য ব্যাকট্র্যাস কল করার কোনও উপায় আছে কি?



ব্যতিক্রমটি ধরুন এবং দেখুন অভ্যন্তরীণ বার্তাটি কী। যেহেতু এটি একটি ব্যতিক্রম স্ট্যান্ডার্ড ব্যতিক্রম (স্ট্যান্ডার্ড :: রানটাইম_অররর) থেকে প্রাপ্ত হওয়া ভাল অভ্যাস, আপনি ক্যাচ দিয়ে এটি ধরতে সক্ষম হবেন (স্ট্যান্ড :: ব্যতিক্রম কনস্ট্যান্ড এবং ই)
মার্টিন ইয়র্ক

4
এবং স্টাডি :: ব্যতিক্রম / স্ট্যান্ড :: রানটাইম_অররর একটি ব্যতিক্রমের "পথ" এবং উত্স খুঁজে পাওয়ার সমস্যা সমাধান করে?
ভোলকারক

4
আপনার প্রশ্নের রাজ্য জিডিবি হিসাবে, আমি মনে করি আপনার সমাধানটি ইতিমধ্যে এসও তে রয়েছে: stackoverflow.com/questions/77005/… আমি এখানে বর্ণিত সমাধানটি ব্যবহার করেছি এবং এটি নিখুঁতভাবে কাজ করে।
নিউরো

4
আপনার কোনও ট্যাগের মাধ্যমে ওএস নির্দিষ্ট করা বিবেচনা করা উচিত। যেহেতু আপনি জিডিবি উল্লেখ করেছেন, আমি ধরে নেব আপনি উইন্ডোজ নয় লিনাক্স সমাধান খুঁজছেন।
jschmier

উত্তর:


74

আপনার সমস্যার ডিবাগ করার ক্ষেত্রে এটি ব্যবহার করতে পারে এমন কিছু তথ্য এখানে রয়েছে

যদি কোনও ব্যতিক্রম না ধরা পড়ে তবে বিশেষ লাইব্রেরি ফাংশনটি std::terminate()স্বয়ংক্রিয়ভাবে কল করা হয়। টার্মিনেট আসলে কোনও ফাংশনের পয়েন্টার এবং ডিফল্ট মান হ'ল স্ট্যান্ডার্ড সি লাইব্রেরি ফাংশন std::abort()। যদি কোনও অপ্রয়োজনীয় ব্যতিক্রমের জন্য কোনও পরিষ্কার-পরিচ্ছন্নতা না ঘটে † তবে এটি কোনও সমস্যা ধ্বংসকারীকে ডাকা না হওয়ায় এটি এই সমস্যাটি ডিবাগ করতে আসলে সহায়ক হতে পারে।
† স্ট্যাকটি অযৌক্তিক std::terminate()বলা হওয়ার আগে এটি বাস্তবায়ন-সংজ্ঞায়িত ।


একটি কল abort()প্রায়শই একটি মূল ডাম্প তৈরির ক্ষেত্রে দরকারী যা ব্যতিক্রমের কারণ নির্ধারণ করার জন্য বিশ্লেষণ করা যেতে পারে। নিশ্চিত হয়ে নিন যে আপনি ulimit -c unlimited(লিনাক্স) মাধ্যমে কোর ডাম্প সক্ষম করেছেন ।


আপনি নিজের terminate()ফাংশনটি ব্যবহার করে ইনস্টল করতে পারেন std::set_terminate()। আপনার জিডিবিতে আপনার সমাপ্তির কার্যক্রমে ব্রেক ব্রেকপয়েন্ট সেট করতে সক্ষম হওয়া উচিত। আপনি পারে আপনার থেকে একটি স্ট্যাক ব্যাক-ট্রেস উত্পাদন করতে সক্ষম হতে terminate()এই ব্যাক-ট্রেস ফাংশন এবং পারে ব্যতিক্রমের অবস্থান চিহ্নিত করতে সহায়তা করে।

সেখানে এক সংক্ষিপ্ত আলোচনা uncaught ব্যতিক্রম মধ্যে সি ব্রুস Eckel চিন্তার ++ 2nd এড যে হিসাবে ভাল সহায়ক হতে পারে।


যেহেতু ডিফল্টরূপে terminate()কলগুলি abort()(যেটি ডিফল্টরূপে SIGABRTসংকেতের কারণ হয়ে দাঁড়ায় ), আপনি একটি হ্যান্ডলার সেট করতে এবং তারপরে সংকেত হ্যান্ডলারের মধ্যে থেকে একটি স্ট্যাক ব্যাকট্রেস মুদ্রণ করতে সক্ষম হতে পারেন । এই ব্যাকট্রেস ব্যতিক্রমটির অবস্থান সনাক্ত করতে সহায়তা করতে পারে।SIGABRT


নোট: আমি বলতে may পৃথক ত্রুটি পরিচালনা ভাষা নির্মান ব্যবহারের মাধ্যমে সি ++ সমর্থন অ-স্থানীয় ত্রুটি পরিচালনা এবং সাধারণ কোড থেকে কোড প্রতিবেদন কারণ। ক্যাচ ব্লকটি হতে পারে এবং প্রায়শই নিক্ষেপকরণের চেয়ে পৃথক ফাংশন / পদ্ধতিতে থাকে। মন্তব্যগুলিতে আমার কাছে এটিও ইশারা করা হয়েছে (ধন্যবাদ ড্যান ) যে স্ট্যাকটি ডাকার আগে terminate()এটি অযৌক্তিক ছিল কিনা তা বাস্তবায়ন-সংজ্ঞায়িত ।

আপডেট: আমি একটি লিনাক্স পরীক্ষা প্রোগ্রাম একসাথে নিক্ষেপ করেছি যা একটি terminate()ফাংশন সেটের মাধ্যমে একটি ব্যাকট্রেস set_terminate()এবং অন্যটির জন্য একটি সিগন্যাল হ্যান্ডলারের উত্পন্ন করে SIGABRT। দুটি ব্যাকট্রেস সঠিকভাবে আনহ্যান্ডেল ব্যতিক্রমের অবস্থানটি প্রদর্শন করে।

আপডেট 2: টার্মিনেটের মধ্যে অপ্রত্যাশিত ব্যতিক্রমগুলি ধরার বিষয়ে একটি ব্লগ পোস্টকে ধন্যবাদ , আমি কয়েকটি নতুন কৌশল শিখলাম; সমাপ্ত হ্যান্ডলারের মধ্যে অব্যাহত ব্যতিক্রম পুনরায় নিক্ষেপ সহ। এটি লক্ষ করা গুরুত্বপূর্ণ যে throwকাস্টম টার্মিনেট হ্যান্ডলারের মধ্যে খালি বিবৃতিটি জিসিসির সাথে কাজ করে এবং এটি কোনও বহনযোগ্য সমাধান নয়।

কোড:

#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);
}

আউটপুট:

my_terminate অনিচ্ছাকৃত ব্যতিক্রম ধরা পড়ে। কি (): রুনটাইম এয়ার!
my_terminate backtrace 10 টি ফ্রেম ফিরিয়েছে

[বিটি]: (0)। / টেক্সটমি_মিটারমিট__এফভি+0x1 এ) [0x8048e52]
[বিটি]: (১) / সমুদ্র / লিবি / লিবিস্টডিসি++-libc6.2-2.so.3 [0x40045baa]
[বিটি]: (২) / উত্তর / লিবি / লিবিস্টডিসি++-libc6.2-2.so.3 [0x400468e5]
[বিটি]: (৩) / ওএসআর / লিবি / লিবিস্টডিসি++-libc6.2-2.so.3(__ পুনরায় +0xaf) [0x40046 বিডিএফ]
[বিটি]: (৪) ./ সেরা( থ্রো_ এক্সসেপশন__এফভি+0x68) [0x8049008]
[বিটি]: (৫) ./est(foo2__Fv+0xb) [0x8049043]
[বিটি]: ()) ./est(foo1__Fv+0xb) [0x8049057]
[বিটি]: ()) ./est(main+0xc1) [0x8049121]
[বিটি]: (8) ./est(__libc_start_main+0x95) [0x42017589]
[বিটি]: (9) ./est(__eh_alloc+0x3d) [0x8048b21]

সংকেত 6 (বাতিল), 0x42029331 থেকে ঠিকানা 0x1239 is
crit_err_hdlr ব্যাকট্রেস 13 ফ্রেম ফিরেছে

[বিটি]: (১) ./est(kill+0x11) [0x42029331]
[বিটি]: (২) ./est(abort+0x16e) [0x4202a8c2]
[বিটি]: (৩)। / সেরা [0x8048f9f]
[বিটি]: (৪) / ওসির / লিবি / লিবিস্টডিসি++-libc6.2-2.so.3 [0x40045baa]
[বিটি]: (৫) / ওএসআর / লিবি / লিবিস্টডিসি++-libc6.2-2.so.3 [0x400468e5]
[বিটি]: ()) / ওএসআর / লিবি / লিবিস্টডিসি++-libc6.2-2.so.3(__ পুনরায় +0xaf) [0x40046 বিডিএফ]
[বিটি]: ())।
[বিটি]: (8) ./est(foo2__Fv+0xb) [0x8049043]
[বিটি]: (9) ./est(foo1__Fv+0xb) [0x8049057]
[বিটি]: (10) ./est(main+0xc1) [0x8049121]
[বিটি]: (১১) ./est(__libc_start_main+0x95) [0x42017589]
[বিটি]: (12) ./est(__eh_alloc+0x3d) [0x8048b21]


4
অনেক আগ্রহব্যাঞ্জক. আমি সর্বদা সন্দেহ করেছিলাম যে একটি অপরিশোধিত ব্যতিক্রম স্ট্যাকটি উন্মুক্ত করবে যতক্ষণ না এটি শীর্ষ স্তরে ( main) পৌঁছে যায় এবং তারপরে এটি কল করবে terminate()। তবে আপনার উদাহরণটি দেখায় যে কোনও আনইন্ডিং মোটেও করা হয় না, যা খুব দুর্দান্ত।
ড্যান

6
1) throw(int)অনুমান অপ্রয়োজনীয়। ২) uc->uc_mcontext.eipসম্ভবত এটি খুব প্ল্যাটফর্ম নির্ভর (যেমন ...ripa৪-বিট প্ল্যাটফর্মের ব্যবহার)। 3) -rdynamicআপনি ব্যাকট্রাস প্রতীক পেতে তাই সংকলন । 4) ./a.out 2>&1 | c++filtচমত্কার ব্যাকট্রিজ প্রতীক পেতে চালান ।
ড্যান

4
"অপ্রকাশিত ব্যতিক্রমের জন্য কোনও পরিষ্কার-পরিচ্ছন্নতা ঘটে না।" - আসলে, এটি বাস্তবায়ন-সংজ্ঞায়িত। 15 + / 9 এবং সি ++ স্পকে 15.5.1 / 2 দেখুন। "এমন পরিস্থিতিতে যেখানে কোনও ম্যাচিং হ্যান্ডলার পাওয়া যায় না, এটি সমাপ্তি () বলা হওয়ার আগে স্ট্যাকটি অযাচিত কিনা তা বাস্তবায়ন-সংজ্ঞায়িত।" তবুও, যদি আপনার সংকলক এটি সমর্থন করে তবে এটি দুর্দান্ত সমাধান!
ড্যান

4
((sig_ucontext_t *)userContext)->uc_mcontext.fault_address;আমার এআরএম টার্গেটের জন্য কাজ করেছেন
স্টিফেন

4
কয়েকটি নোট: ব্যাকট্রেস_সিম্বলস () একটি ম্যালোক করে ... সুতরাং, আপনি শুরুতে মেমরির একটি ব্লক প্রাক-বরাদ্দ করতে চাইতে পারেন, তারপরে আপনি যে ইভেন্টটি হবেন তার পিছনে ব্যাকট্রেস_সিম্বলস () কল করার আগে এটি my_terminate () এ বাতিল করুন ocate একটি স্ট্যান্ডিং হ্যান্ডলিং: Bad_alloc () ব্যতিক্রম। এছাড়াও, আপনি <cxxabi.h> অন্তর্ভুক্ত করতে পারেন এবং তারপরে আউটপুট বার্তাগুলির [] স্ট্রিংগুলিতে '(' এবং '+' এর মধ্যে প্রদর্শিত ম্যাংলেড স্ট্রাস্টিং থেকে কিছু দরকারী করতে __cxa_demangle () ব্যবহার করতে পারেন
কে স্কট পিল

51

আপনি যেমনটি বলেছেন, আমরা জিডিবিতে 'ক্যাচ থ্রো' ব্যবহার করতে পারি এবং প্রতিটি থ্রো করা ব্যতিক্রমের জন্য 'ব্যাকট্র্যাস' কল করতে পারি। যদিও এটি ম্যানুয়ালি করার জন্য সাধারণত খুব ক্লান্তিকর, জিডিবি প্রক্রিয়াটির অটোমেশনের অনুমতি দেয়। এটি সর্বশেষ অপ্রকাশিত একটি সহ, ছুঁড়ে ফেলা সমস্ত ব্যতিক্রমের ব্যাকট্রেসটি দেখতে দেয়:

gdb>

set pagination off
catch throw
commands
backtrace
continue
end
run

আর ম্যানুয়াল হস্তক্ষেপ ছাড়াই, এটি শেষ ব্যতীত ব্যতীত একটি সহ অনেকগুলি ব্যাকট্রেস উত্পন্ন করে:

Catchpoint 1 (exception thrown), 0x00a30 in __cxa_throw () from libstdc++.so.6
#0  0x0da30 in __cxa_throw () from /usr/.../libstdc++.so.6
#1  0x021f2 in std::__throw_bad_weak_ptr () at .../shared_ptr_base.h:76
[...]
terminate called after throwing an instance of 'std::bad_weak_ptr'
  what():  bad_weak_ptr
Program received signal SIGABRT, Aborted.

এটি মোড়ানো একটি দুর্দান্ত ব্লগ পোস্ট এখানে: http://741mhz.com/throw-stacktrace [ সংরক্ষণাগার.অর্গ উপর]


17

আপনি এর মতো ম্যাক্রো তৈরি করতে পারেন:

#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, __LINE__, (message) )

... এবং এটি আপনাকে সেই স্থানটি দেবে যেখানে ব্যতিক্রম ছুঁড়ে ফেলা হয়েছে (স্বীকার করা হবে স্ট্যাকের ট্রেস নয়)। উপরের কনস্ট্রাক্টর গ্রহণকারী কিছু বেস বর্গ থেকে আপনার ব্যতিক্রমগুলি গ্রহণ করা আপনার পক্ষে প্রয়োজনীয়।


18
-1 আপনি না throw new excation(...)তবে throw exception(...)সি ++ জাভা নয়,
আরটিয়াম

7
ঠিক আছে, আমি এটা ঠিক করেছি। এমন কোনও প্রোগ্রামারকে ক্ষমা করবেন যা জাভা এবং সি ++ উভয় ক্ষেত্রেই কাজ করে?
এরিক হারম্যানসেন

আমি এটি ব্যবহার করেছি। এটির সাথে সমস্যাটি হ'ল এটি ব্যতিক্রমটি আসলে কী ছুঁড়েছে তা তা বলে না। উদাহরণস্বরূপ যদি আপনার একটি ট্রাই ব্লকে ৫ টি স্টোই কল থাকে তবে আপনি জানেন না যে আসলে কোনটি অপরাধী।
বানজোক্যাট

5

আপনি কী ওএস / সংকলক ব্যবহার করেন সে সম্পর্কে আপনি কোনও তথ্য দেননি।

ভিজ্যুয়াল স্টুডিওতে সি ++ ব্যতিক্রমগুলি চালিত হতে পারে।

দেখুন "ভিসুয়াল সি ++ ব্যতিক্রম নিয়ন্ত্রণ যন্ত্রানুষঙ্গের" ddj.com উপর

আমার নিবন্ধ "পোস্টমর্টেম ডিবাগিং" , এছাড়াও ddj.com এ উইন 32 স্ট্রাকচার্ড ব্যতিক্রম হ্যান্ডলিং (যন্ত্র দ্বারা ব্যবহৃত) লগিংয়ের জন্য ব্যবহার করার কোড অন্তর্ভুক্ত রয়েছে etc.


তিনি বলেন, জিডিবি, যা উইন্ডোজ / ভিজ্যুয়াল স্টুডিওর পক্ষে অনেকটাই নিয়মকানুন।
বেন ভয়েগট

4
ঠিক আছে, তিনি বলেছেন যে তিনি "শর্ট অফ জিডিবি" চান তবে তিনি স্পষ্টভাবে কোনও ওএস / সংকলককে উল্লেখ করেন না। লোকেরা এ জাতীয় স্টাফ ঘোষণা না করার সমস্যা বলে Tha
রেড সফ্ট অ্যাডায়ার

5

আপনি noexceptএকটি ব্যতিক্রম চিহ্নিত করার জন্য আপনার কোডের প্রধান শক্ত স্থান চিহ্নিত করতে পারেন , তারপরে লিবুনউইন্ড ব্যবহার করুন (কেবলমাত্র -lunwindলিঙ্কার প্যারামিটারগুলিতে যুক্ত করুন) (এর সাথে পরীক্ষিত clang++ 3.6):

demagle.hpp:

#pragma once

char const *
get_demangled_name(char const * const symbol) noexcept;

demangle.cpp:

#include "demangle.hpp"

#include <memory>

#include <cstdlib>

#include <cxxabi.h>

namespace
{

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
std::unique_ptr< char, decltype(std::free) & > demangled_name{nullptr, std::free};
#pragma clang diagnostic pop

}

char const *
get_demangled_name(char const * const symbol) noexcept
{
    if (!symbol) {
        return "<null>";
    }
    int status = -4;
    demangled_name.reset(abi::__cxa_demangle(symbol, demangled_name.release(), nullptr, &status));
    return ((status == 0) ? demangled_name.get() : symbol);
}

backtrace.hpp:

#pragma once
#include <ostream>

void
backtrace(std::ostream & _out) noexcept;

backtrace.cpp:

#include "backtrace.hpp"

#include <iostream>
#include <iomanip>
#include <limits>
#include <ostream>

#include <cstdint>

#define UNW_LOCAL_ONLY
#include <libunwind.h>

namespace
{

void
print_reg(std::ostream & _out, unw_word_t reg) noexcept
{
    constexpr std::size_t address_width = std::numeric_limits< std::uintptr_t >::digits / 4;
    _out << "0x" << std::setfill('0') << std::setw(address_width) << reg;
}

char symbol[1024];

}

void
backtrace(std::ostream & _out) noexcept
{
    unw_cursor_t cursor;
    unw_context_t context;
    unw_getcontext(&context);
    unw_init_local(&cursor, &context);
    _out << std::hex << std::uppercase;
    while (0 < unw_step(&cursor)) {
        unw_word_t ip = 0;
        unw_get_reg(&cursor, UNW_REG_IP, &ip);
        if (ip == 0) {
            break;
        }
        unw_word_t sp = 0;
        unw_get_reg(&cursor, UNW_REG_SP, &sp);
        print_reg(_out, ip);
        _out << ": (SP:";
        print_reg(_out, sp);
        _out << ") ";
        unw_word_t offset = 0;
        if (unw_get_proc_name(&cursor, symbol, sizeof(symbol), &offset) == 0) {
            _out << "(" << get_demangled_name(symbol) << " + 0x" << offset << ")\n\n";
        } else {
            _out << "-- error: unable to obtain symbol name for this frame\n\n";
        }
    }
    _out << std::flush;
}

backtrace_on_terminate.hpp:

#include "demangle.hpp"
#include "backtrace.hpp"

#include <iostream>
#include <type_traits>
#include <exception>
#include <memory>
#include <typeinfo>

#include <cstdlib>

#include <cxxabi.h>

namespace
{

[[noreturn]]
void
backtrace_on_terminate() noexcept;

static_assert(std::is_same< std::terminate_handler, decltype(&backtrace_on_terminate) >{});

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
std::unique_ptr< std::remove_pointer_t< std::terminate_handler >, decltype(std::set_terminate) & > terminate_handler{std::set_terminate(backtrace_on_terminate), std::set_terminate};
#pragma clang diagnostic pop

[[noreturn]]
void
backtrace_on_terminate() noexcept
{
    std::set_terminate(terminate_handler.release()); // to avoid infinite looping if any
    backtrace(std::clog);
    if (std::exception_ptr ep = std::current_exception()) {
        try {
            std::rethrow_exception(ep);
        } catch (std::exception const & e) {
            std::clog << "backtrace: unhandled exception std::exception:what(): " << e.what() << std::endl;
        } catch (...) {
            if (std::type_info * et = abi::__cxa_current_exception_type()) {
                std::clog << "backtrace: unhandled exception type: " << get_demangled_name(et->name()) << std::endl;
            } else {
                std::clog << "backtrace: unhandled unknown exception" << std::endl;
            }
        }
    }
    std::_Exit(EXIT_FAILURE); // change to desired return code
}

}

ইস্যু সম্পর্কে ভাল নিবন্ধ আছে ।


1

আমি উইন্ডোজ / ভিজ্যুয়াল স্টুডিওতে এটি করার কোড পেয়েছি, আপনি যদি একটি রূপরেখা চান তবে আমাকে জানান। বামন 2 কোডের জন্য এটি কীভাবে করবেন তা জানেন না, তবে একটি দ্রুত গুগল পরামর্শ দেয় যে লিবিগিসিই-তে একটি ফাংশন _উইনওয়াইন্ড_ব্যাকট্রেস রয়েছে যা সম্ভবত আপনার প্রয়োজনের অংশ।


সম্ভবত কারণ "আপনি যদি একটি রূপরেখা চান তবে আমাকে জানান" কোনও দরকারী উত্তর নয়। তবে _উইন্ডওয়াইন্ড_ব্যাকট্রেস; ক্ষতিপূরণ
থমাস

যে ভিত্তিতে ওপি জিডিবি উল্লেখ করেছে, আমি অনুমান করেছি যে উইন্ডোজ প্রাসঙ্গিক নয়। অ্যালেক্স অবশ্যই উইন্ডোজ বলতে তাঁর প্রশ্ন সম্পাদনা করতে নির্দ্বিধায় ছিল।
বেন ভয়েগট

1

এই থ্রেডটি পরীক্ষা করুন, সম্ভবত এটি সহায়তা করে:

সমস্ত আনহ্যান্ডেল সি ++ ব্যতিক্রম ধরা হচ্ছে?

আমি সেই সফ্টওয়্যারটি দিয়ে ভাল অভিজ্ঞতা করেছি:

http://www.codeproject.com/KB/applications/blackbox.aspx

এটি কোনও আনহ্যান্ডেল ব্যতিক্রমের জন্য কোনও স্ট্যাকের স্ট্যাক ট্রেস মুদ্রণ করতে পারে।


আমি মনে করি মুল বক্তব্যটি হ'ল অ্যালেক্স exception thrown foo.c@54, ..., re-thrown bar.c@54, ....ম্যানুয়ালি না করেই স্ট্যাকট্রেস চান ।
ভোলকারক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.