কীভাবে কেউ সিটিতে একটি স্ট্যাক ট্রেস দখল করতে পারে?


83

আমি জানি এটি করার জন্য কোনও স্ট্যান্ডার্ড সি ফাংশন নেই। আমি ভাবছিলাম যে উইন্ডোজ এবং * নিক্সে এর কৌশলগুলি কী? (এই মুহূর্তে এটি করার জন্য উইন্ডোজ এক্সপি আমার অতি গুরুত্বপূর্ণ ওএস))


আমি বিস্তারিতভাবে বিভিন্ন পদ্ধতি পরীক্ষিত হয়েছে: stackoverflow.com/questions/3899870/print-call-stack-in-c-or-c/...
সিরো Santilli郝海东冠状病六四事件法轮功

উত্তর:


81

glibc ব্যাকট্রেস () ফাংশন সরবরাহ করে।

http://www.gnu.org/software/libc/manual/html_node/Backtraces.html


7
glibc FTW ... আবার। (এটি সি প্রোগ্রামিংয়ের ক্ষেত্রে যখন আমি গ্লিবিককে পরম স্বর্ণের মান হিসাবে বিবেচনা করি তখনও এটি আর একটি কারণ (এটি এবং এটির সাথে যে সংকলকটি যায়))
ট্রেভর বয়েড স্মিথ

4
তবে আরও অপেক্ষা করুন! ব্যাকট্রেস () ফাংশনটি কেবল কলস্ট্যাক ফাংশনগুলিকে প্রতিনিধিত্ব করে * অকার্যকর * পয়েন্টারগুলির একটি অ্যারে সরবরাহ করে। "এটি খুব কার্যকর নয় ar ভয় নেই! গ্লিবসি একটি ফাংশন সরবরাহ করে যা সমস্ত শূন্য * ঠিকানা (কলস্ট্যাক ফাংশন ঠিকানা) মানব পঠনযোগ্য স্ট্রিং প্রতীকগুলিতে রূপান্তর করে। char ** backtrace_symbols (void *const *buffer, int size)
ট্রেভর বয়েড স্মিথ

4
ক্যাভ্যাট: কেবল সি ফাংশনগুলির জন্যই কাজ করে, আমি মনে করি। @ ট্র্যাভোর: এটি ইএলএফ সারণীতে ঠিকানার মতো সিম সন্ধান করছে।
কনরাড মেয়ার

4
এছাড়াও আছে void backtrace_symbols_fd(void *const *buffer, int size, int fd)যা উদাহরণস্বরূপ আউটপুট সরাসরি stdout / err এ প্রেরণ করতে পারে।
wkz

4
backtrace_symbols()স্তন্যপান। এটির জন্য সমস্ত প্রতীক রফতানি করা দরকার এবং এটি DWARF (ডিবাগিং) প্রতীকগুলিকে সমর্থন করে না। অনেকগুলি (সর্বাধিক) ক্ষেত্রে libbacktrace একটি আরও ভাল বিকল্প।
এরওয়ান লেগ্রান্ড

29

এখানে ব্যাকট্রিজ (), এবং ব্যাকট্র্যাস_সিম্বলস () রয়েছে:

ম্যান পৃষ্ঠা থেকে:

এটিকে আরও সুবিধাজনক / 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);
    }
};

...

তা দা!

দ্রষ্টব্য: অপ্টিমাইজেশন পতাকাগুলি সক্ষম করা ফলস্বরূপ স্ট্যাকের ট্রেসকে ভুল করে তুলতে পারে। আদর্শভাবে, কেউ এই ক্ষমতাটি ডিবাগ পতাকা এবং অপ্টিমাইজেশন পতাকা বন্ধ সহ ব্যবহার করতে পারে।


@ শুক কেবল ঠিকানাটিকে একটি চিহ্নের স্ট্রিংয়ে রূপান্তর করার জন্য, যা প্রয়োজনে অন্যান্য সরঞ্জাম ব্যবহার করে বাহ্যিকভাবে করা যেতে পারে।
উড্রো বারলো

22

উইন্ডোজের জন্য স্ট্যাকওয়ালক 64 () এপিআই পরীক্ষা করুন (32 বিট উইন্ডোজটিতেও)। ইউনিক্সের জন্য আপনার এটির ওএসের স্থানীয় উপায়টি ব্যবহার করা উচিত, না যদি অবলম্বনে থাকে তবে গ্লিবসি'র ব্যাকট্র্যাসে ফ্যালব্যাক করুন।

তবে নোট করুন যে নেটিভ কোডে স্ট্যাকট্রেস গ্রহণ করা খুব কমই একটি ভাল ধারণা - এটি সম্ভব নয় বলে নয়, আপনি সাধারণভাবে ভুল জিনিস অর্জন করার চেষ্টা করছেন বলে।

বেশিরভাগ সময় লোকেরা একটি ব্যতিক্রমী পরিস্থিতি যেমন একটি ব্যতিক্রম ধরা পড়ে তখন একটি দৃsert় ব্যর্থ হয় বা - সবচেয়ে খারাপ এবং সবচেয়ে খারাপ - যখন আপনি একটি মারাত্মক "ব্যতিক্রম" বা সংকেত পেতে চাইলে একটি ব্যতিক্রমী পরিস্থিতি পেতে চেষ্টা করেন of বিভাজন লঙ্ঘন।

শেষ ইস্যুটি বিবেচনা করে, বেশিরভাগ এপিআইগুলির জন্য আপনাকে স্পষ্টভাবে মেমরি বরাদ্দ করতে হবে বা এটি অভ্যন্তরীণভাবে করতে পারে। আপনার প্রোগ্রামটি বর্তমানে যে ভঙ্গুর অবস্থায় রয়েছে তাতে এটি করার ফলে তীব্রভাবে জিনিসগুলি আরও খারাপ হতে পারে। উদাহরণস্বরূপ, ক্র্যাশ প্রতিবেদন (বা কর্ড্প) সমস্যার প্রকৃত কারণ প্রতিফলিত করবে না, তবে এটি পরিচালনা করার জন্য আপনার ব্যর্থ প্রচেষ্টা)।

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


4
আপনি একটি সিগন্যাল বা ব্যতিক্রম হ্যান্ডলারের মধ্যে মেমরি বরাদ্দ চেষ্টা করার ভঙ্গুর হওয়ার কথা ঠিক। একটি সম্ভাব্য উপায় হ'ল প্রোগ্রাম শুরু করার সময় একটি নির্দিষ্ট পরিমাণ "জরুরি" স্থান বরাদ্দ করা, বা একটি স্ট্যাটিক বাফার ব্যবহার করা।
j_random_hacker

অন্য উপায় হ'ল একটি
করডাম্প

5

আপনার আনইন্ড লাইব্রেরি ব্যবহার করা উচিত ।

আপনি যদি ভাগ করা লাইব্রেরি থেকে কল না করেন তবে আপনার দৃষ্টিভঙ্গিও ঠিকঠাক কাজ করবে।

addr2lineসংশ্লিষ্ট পিসির উত্স ফাংশন / লাইন নম্বর পেতে আপনি লিনাক্সের কমান্ডটি ব্যবহার করতে পারেন ।


"উত্স ফাংশন / লাইন নম্বর"? লিঙ্কিং যদি হ্রাস কোড আকারের জন্য অনুকূলিত হয়? আমি বলব, যদিও এটি একটি দরকারী প্রকল্পের মতো দেখাচ্ছে। দুঃখের বিষয় যা নিবন্ধগুলি পাওয়ার কোনও উপায় নেই। আমি অবশ্যই এটি দেখতে হবে। আপনি কি জানেন যে এটি সম্পূর্ণ প্রসেসর স্বাধীন? একটি সি সংকলক রয়েছে এমন যে কোনও কিছুতে কেবল কাজ করে?
মাওগ বলছেন মনিকা

4
ঠিক আছে, এই মন্তব্যটি মূল্যবান ছিল, কেবলমাত্র সহায়ক অ্যাডার 2 লাইন আদেশের কারণেই!
ওগ্রে গীতসংহিতা 33

অ্যাডআরলাইন ASLR (যেমন বিগত দশকে লোকেরা ব্যবহার করে আসছে বেশিরভাগ) সহ সিস্টেমে রিসোকেটেবল কোডে ব্যর্থ।
এরওয়ান লেগ্রান্ড

4

এটি করার মতো কোনও প্ল্যাটফর্ম নেই।

আপনি করতে পারেন নিকটতম জিনিসটি অপটিমাইজেশন ছাড়াই কোড চালানো। এই পদ্ধতিতে আপনি প্রসেসটি সংযুক্ত করতে পারবেন (ভিজ্যুয়াল সি ++ ডিবাগার বা জিডিবি ব্যবহার করে) এবং ব্যবহারযোগ্য স্ট্যাক ট্রেস পাবেন।


ক্ষেত্রের এম্বেড থাকা কম্পিউটারে ক্রাশ হওয়ার পরে এটি আমার সহায়তা করে না। :(
কেভিন

@ কেভিন: এম্বেড থাকা মেশিনেও, সাধারণত একটি রিমোট ডিবাগার স্টাব বা কমপক্ষে একটি কোর ডাম্প পাওয়ার উপায় রয়েছে। এটি একবার মাঠে মোতায়েন না হলেও, ...
আগাম

আপনি যদি আপনার পছন্দের উইন্ডোজ / লিনাক্স / ম্যাকের প্ল্যাটফর্মে জিসিসি-গ্লিব্যাক ব্যবহার করে চালনা করেন ... তবে ব্যাকট্র্যাস () এবং ব্যাকট্র্যাস_সাইমবোলস () তিনটি প্ল্যাটফর্মে কাজ করবে। উক্ত বিবৃতিটি দেওয়াতে, আমি "এটি করার কোনও [পোর্টেবল] উপায় নেই" শব্দটি ব্যবহার করব।
ট্রেভর বয়ড স্মিথ

4

উইন্ডোজের CaptureStackBackTrace()জন্যও এটি একটি বিকল্প, যা ব্যবহারকারীর শেষের চেয়ে কম প্রস্তুতির কোডের প্রয়োজন StackWalk64()। (এছাড়াও, আমার মতো একই দৃশ্যের জন্য, CaptureStackBackTrace()আরও ভাল (আরও নির্ভরযোগ্যভাবে) কাজ করা শেষ হয়েছিল) StackWalk64())


2

সোলারিসের pstack কমান্ড রয়েছে, এটি লিনাক্সেও অনুলিপি করা হয়েছিল।


4
দরকারী, কিন্তু আসলে সি নয় (এটি একটি বাহ্যিক উপযোগ)।
প্রশংসিত

4
এছাড়াও, বিবরণ থেকে (বিভাগ: সীমাবদ্ধতা) ": pstack বর্তমানে শুধুমাত্র লিনাক্সে কাজ করে, কেবলমাত্র একটি x86 মেশিনে 32 বিট ইএলএফ বাইনারি (64 বিট সমর্থিত নয়)"
সিওরো কোস্টা

0

আপনি স্ট্যাকটি পিছনের দিকে হাঁটা করে এটি করতে পারেন। বাস্তবে, যদিও, প্রতিটি ক্রিয়াকলাপের শুরুতে একটি কল স্ট্যাকের সাথে একটি শনাক্তকারী যুক্ত করা এবং এটি শেষে পপ করা প্রায়শই সহজ then এটি PITA এর কিছুটা, তবে এটি কার্যকরভাবে কাজ করে এবং শেষ পর্যন্ত আপনার সময় বাঁচায়।


4
আপনি আরও "পুরোপুরি পিছনে পিছনে হাঁটা" ব্যাখ্যা করতে পারেন?
স্পাইডি

এমপিডেড সিস্টেমগুলিতে @ স্পিডি, কখনও কখনও আপনার কাছে যা কিছু থাকে - আমার ধারণা, এটি ভোট দেওয়া হয়েছে কারণ প্ল্যাটফর্মটি উইনএক্সপি। তবে একটি লিবিসি ছাড়াই যা স্ট্যাক হাঁটা সমর্থন করে, মূলত আপনাকে স্ট্যাকটি "হাঁটা" করতে হবে। আপনি বর্তমান বেস পয়েন্টার দিয়ে শুরু করুন (x86 এ এটি আরবিপি রেগের বিষয়বস্তু)। এটি আপনাকে 1 দিয়ে স্ট্যাকের দিকে নির্দেশ করবে to সংরক্ষিত পূর্ববর্তী আরবিপি (এইভাবে স্ট্যাকটি চলতে থাকবে), এবং ২ কল / শাখা ফেরতের ঠিকানা (কলিং ফাংশনটির সংরক্ষিত আরআইপি রেজি), যা আপনাকে জানায় যে ফাংশনটি কী ছিল। তারপরে, আপনার যদি প্রতীক টেবিলটিতে অ্যাক্সেস থাকে তবে আপনি ফাংশন ঠিকানাটি সন্ধান করতে পারেন।
টেড মিডলটন

0

বিগত কয়েক বছর ধরে আমি আয়ান ল্যান্স টেলরের লাইবব্যাকট্রেস ব্যবহার করছি। এটি জিএনইউ সি লাইব্রেরির ফাংশনগুলির চেয়ে অনেক বেশি পরিষ্কার, যার জন্য সমস্ত চিহ্নগুলি রফতানি করতে হবে। এটি লাইবুনউইন্ডের চেয়ে ব্যাকট্রেস জেনারেশনের জন্য আরও বেশি ইউটিলিটি সরবরাহ করে। এবং সর্বশেষে তবে অন্তত: এএসএলআর দ্বারা এটি পরাজিত হয় না যেমন বাইরের সরঞ্জামগুলির যেমন প্রয়োজন হয় addr2line

লিবিব্র্যাট্রেস প্রথমে জিসিসি বিতরণের অংশ ছিল তবে এটি এখন বিএসডি লাইসেন্সের অধীনে লেখক একটি স্ট্যান্ডলোন লাইব্রেরি হিসাবে উপলব্ধ করেছেন:

https://github.com/ianlancetaylor/libbacktrace

লেখার সময়, আমি যদি এমন প্ল্যাটফর্মের ব্যাকট্রেস উত্পন্ন করার প্রয়োজন না করি যা libbacktrace দ্বারা সমর্থিত না হয় তবে আমি আর কিছুই ব্যবহার করব না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.