আমি জানি এটি করার জন্য কোনও স্ট্যান্ডার্ড সি ফাংশন নেই। আমি ভাবছিলাম যে উইন্ডোজ এবং * নিক্সে এর কৌশলগুলি কী? (এই মুহূর্তে এটি করার জন্য উইন্ডোজ এক্সপি আমার অতি গুরুত্বপূর্ণ ওএস))
আমি জানি এটি করার জন্য কোনও স্ট্যান্ডার্ড সি ফাংশন নেই। আমি ভাবছিলাম যে উইন্ডোজ এবং * নিক্সে এর কৌশলগুলি কী? (এই মুহূর্তে এটি করার জন্য উইন্ডোজ এক্সপি আমার অতি গুরুত্বপূর্ণ ওএস))
উত্তর:
glibc ব্যাকট্রেস () ফাংশন সরবরাহ করে।
http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
char ** backtrace_symbols (void *const *buffer, int size)
void backtrace_symbols_fd(void *const *buffer, int size, int fd)
যা উদাহরণস্বরূপ আউটপুট সরাসরি stdout / err এ প্রেরণ করতে পারে।
backtrace_symbols()
স্তন্যপান। এটির জন্য সমস্ত প্রতীক রফতানি করা দরকার এবং এটি DWARF (ডিবাগিং) প্রতীকগুলিকে সমর্থন করে না। অনেকগুলি (সর্বাধিক) ক্ষেত্রে libbacktrace একটি আরও ভাল বিকল্প।
এখানে ব্যাকট্রিজ (), এবং ব্যাকট্র্যাস_সিম্বলস () রয়েছে:
ম্যান পৃষ্ঠা থেকে:
#include <execinfo.h>
#include <stdio.h>
...
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
for (i = 0; i < frames; ++i) {
printf("%s\n", strs[i]);
}
free(strs);
...
এটিকে আরও সুবিধাজনক / OOP উপায়ে ব্যবহার করার একটি উপায় ব্যতিক্রম ট্র্যাক্ট কনস্ট্রাক্টরের ব্যাকট্র্যাস_সাইমবোলস () এর ফলাফল সংরক্ষণ করা। সুতরাং, আপনি যখনই এই ধরণের ব্যতিক্রম ছুঁড়ে ফেলেন তখন আপনার স্ট্যাক ট্রেস রয়েছে। তারপরে, এটি মুদ্রণের জন্য কেবল একটি ফাংশন সরবরাহ করুন। উদাহরণ স্বরূপ:
class MyException : public std::exception {
char ** strs;
MyException( const std::string & message ) {
int i, frames = backtrace(callstack, 128);
strs = backtrace_symbols(callstack, frames);
}
void printStackTrace() {
for (i = 0; i < frames; ++i) {
printf("%s\n", strs[i]);
}
free(strs);
}
};
...
try {
throw MyException("Oops!");
} catch ( MyException e ) {
e.printStackTrace();
}
তা দা!
দ্রষ্টব্য: অপ্টিমাইজেশন পতাকাগুলি সক্ষম করা ফলস্বরূপ স্ট্যাকের ট্রেসকে ভুল করে তুলতে পারে। আদর্শভাবে, কেউ এই ক্ষমতাটি ডিবাগ পতাকা এবং অপ্টিমাইজেশন পতাকা বন্ধ সহ ব্যবহার করতে পারে।
উইন্ডোজের জন্য স্ট্যাকওয়ালক 64 () এপিআই পরীক্ষা করুন (32 বিট উইন্ডোজটিতেও)। ইউনিক্সের জন্য আপনার এটির ওএসের স্থানীয় উপায়টি ব্যবহার করা উচিত, না যদি অবলম্বনে থাকে তবে গ্লিবসি'র ব্যাকট্র্যাসে ফ্যালব্যাক করুন।
তবে নোট করুন যে নেটিভ কোডে স্ট্যাকট্রেস গ্রহণ করা খুব কমই একটি ভাল ধারণা - এটি সম্ভব নয় বলে নয়, আপনি সাধারণভাবে ভুল জিনিস অর্জন করার চেষ্টা করছেন বলে।
বেশিরভাগ সময় লোকেরা একটি ব্যতিক্রমী পরিস্থিতি যেমন একটি ব্যতিক্রম ধরা পড়ে তখন একটি দৃsert় ব্যর্থ হয় বা - সবচেয়ে খারাপ এবং সবচেয়ে খারাপ - যখন আপনি একটি মারাত্মক "ব্যতিক্রম" বা সংকেত পেতে চাইলে একটি ব্যতিক্রমী পরিস্থিতি পেতে চেষ্টা করেন of বিভাজন লঙ্ঘন।
শেষ ইস্যুটি বিবেচনা করে, বেশিরভাগ এপিআইগুলির জন্য আপনাকে স্পষ্টভাবে মেমরি বরাদ্দ করতে হবে বা এটি অভ্যন্তরীণভাবে করতে পারে। আপনার প্রোগ্রামটি বর্তমানে যে ভঙ্গুর অবস্থায় রয়েছে তাতে এটি করার ফলে তীব্রভাবে জিনিসগুলি আরও খারাপ হতে পারে। উদাহরণস্বরূপ, ক্র্যাশ প্রতিবেদন (বা কর্ড্প) সমস্যার প্রকৃত কারণ প্রতিফলিত করবে না, তবে এটি পরিচালনা করার জন্য আপনার ব্যর্থ প্রচেষ্টা)।
আমি ধরে নিয়েছি আপনি সেই মারাত্মক-ত্রুটি-হ্যান্ডলিং জিনিসটি অর্জন করার চেষ্টা করছেন, কারণ বেশিরভাগ লোকেরা মনে হয় এটি যখন স্ট্যাকট্র্যাস পাওয়ার চেষ্টা করে। যদি তা হয় তবে আমি ডিবাগার (বিকাশের সময়) এবং প্রসেসটিকে উত্পাদনের (বা উইন্ডোতে মিনি-ডাম্প) দেবার উপর নির্ভর করব। একসাথে যথাযথ প্রতীক-পরিচালনার সাথে সাথে কারণ কারণের নির্দেশনা ময়না তদন্ত করতে আপনার কোনও সমস্যা হওয়া উচিত নয়।
আপনার আনইন্ড লাইব্রেরি ব্যবহার করা উচিত ।
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
unsigned long a[100];
int ctr = 0;
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
if (ctr >= 10) break;
a[ctr++] = ip;
}
আপনি যদি ভাগ করা লাইব্রেরি থেকে কল না করেন তবে আপনার দৃষ্টিভঙ্গিও ঠিকঠাক কাজ করবে।
addr2line
সংশ্লিষ্ট পিসির উত্স ফাংশন / লাইন নম্বর পেতে আপনি লিনাক্সের কমান্ডটি ব্যবহার করতে পারেন ।
এটি করার মতো কোনও প্ল্যাটফর্ম নেই।
আপনি করতে পারেন নিকটতম জিনিসটি অপটিমাইজেশন ছাড়াই কোড চালানো। এই পদ্ধতিতে আপনি প্রসেসটি সংযুক্ত করতে পারবেন (ভিজ্যুয়াল সি ++ ডিবাগার বা জিডিবি ব্যবহার করে) এবং ব্যবহারযোগ্য স্ট্যাক ট্রেস পাবেন।
উইন্ডোজের CaptureStackBackTrace()
জন্যও এটি একটি বিকল্প, যা ব্যবহারকারীর শেষের চেয়ে কম প্রস্তুতির কোডের প্রয়োজন StackWalk64()
। (এছাড়াও, আমার মতো একই দৃশ্যের জন্য, CaptureStackBackTrace()
আরও ভাল (আরও নির্ভরযোগ্যভাবে) কাজ করা শেষ হয়েছিল) StackWalk64()
)
সোলারিসের pstack কমান্ড রয়েছে, এটি লিনাক্সেও অনুলিপি করা হয়েছিল।
আপনি স্ট্যাকটি পিছনের দিকে হাঁটা করে এটি করতে পারেন। বাস্তবে, যদিও, প্রতিটি ক্রিয়াকলাপের শুরুতে একটি কল স্ট্যাকের সাথে একটি শনাক্তকারী যুক্ত করা এবং এটি শেষে পপ করা প্রায়শই সহজ then এটি PITA এর কিছুটা, তবে এটি কার্যকরভাবে কাজ করে এবং শেষ পর্যন্ত আপনার সময় বাঁচায়।
বিগত কয়েক বছর ধরে আমি আয়ান ল্যান্স টেলরের লাইবব্যাকট্রেস ব্যবহার করছি। এটি জিএনইউ সি লাইব্রেরির ফাংশনগুলির চেয়ে অনেক বেশি পরিষ্কার, যার জন্য সমস্ত চিহ্নগুলি রফতানি করতে হবে। এটি লাইবুনউইন্ডের চেয়ে ব্যাকট্রেস জেনারেশনের জন্য আরও বেশি ইউটিলিটি সরবরাহ করে। এবং সর্বশেষে তবে অন্তত: এএসএলআর দ্বারা এটি পরাজিত হয় না যেমন বাইরের সরঞ্জামগুলির যেমন প্রয়োজন হয় addr2line
।
লিবিব্র্যাট্রেস প্রথমে জিসিসি বিতরণের অংশ ছিল তবে এটি এখন বিএসডি লাইসেন্সের অধীনে লেখক একটি স্ট্যান্ডলোন লাইব্রেরি হিসাবে উপলব্ধ করেছেন:
https://github.com/ianlancetaylor/libbacktrace
লেখার সময়, আমি যদি এমন প্ল্যাটফর্মের ব্যাকট্রেস উত্পন্ন করার প্রয়োজন না করি যা libbacktrace দ্বারা সমর্থিত না হয় তবে আমি আর কিছুই ব্যবহার করব না।