আপনার সমস্যার ডিবাগ করার ক্ষেত্রে এটি ব্যবহার করতে পারে এমন কিছু তথ্য এখানে রয়েছে
যদি কোনও ব্যতিক্রম না ধরা পড়ে তবে বিশেষ লাইব্রেরি ফাংশনটি 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 {
static const bool SET_TERMINATE = std::set_terminate(my_terminate);
}
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;
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";
array[1] = caller_address;
char ** messages = backtrace_symbols(array, size);
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 {
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 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]