কোডের রেখাটি নির্ধারণ করুন যা বিভাগের ত্রুটি ঘটায়?


151

কোডটি কোথায় ভুল রয়েছে সে কারণে এটি কীভাবে নির্ধারণ করে যে সেগমেন্টেশন ত্রুটি সৃষ্টি করে ?

আমার সংকলক ( gcc) প্রোগ্রামের ত্রুটির অবস্থানটি প্রদর্শন করতে পারে ?


5
কোনও জিসিসি / জিডিবি পারে না। সেগফল্টটি কোথায় ঘটেছে তা আপনি সন্ধান করতে পারেন তবে আসল ত্রুটিটি সম্পূর্ণ ভিন্ন জায়গায় হতে পারে।

উত্তর:


218

জিসিসি এটি করতে পারে না তবে জিডিবি (একটি ডিবাগার ) নিশ্চিত করতে পারে। -gস্যুইচটি ব্যবহার করে আপনি এই প্রোগ্রামটি সংকলন করুন :

gcc program.c -g

তারপরে জিডিবি ব্যবহার করুন:

$ gdb ./a.out
(gdb) run
<segfault happens here>
(gdb) backtrace
<offending code is shown here>

এখানেআপনাকে জিডিবি দিয়ে শুরু করার জন্য একটি দুর্দান্ত টিউটোরিয়াল ।

যেখানে সেগফল্ট হয় সাধারণত কোডের যেখানে এটি "ভুল যার কারণ হয়" তা কেবল একটি ক্লু থাকে। প্রদত্ত অবস্থানটি সমস্যাটি যেখানে থাকে তা অগত্যা নয়।


28
দ্রষ্টব্য যে যেখানে সেগফল্টটি ঘটে থাকে তা সাধারণত কোডের যেখানে "ভুলের কারণ হয়" এটি কোডের মধ্যে রয়েছে is একটি গুরুত্বপূর্ণ সূত্র, কিন্তু সমস্যাটি কোথায় থাকে তা অগত্যা নয়।
এমপিজে ০0

9
আপনি আরও বিশদ পেতে (বিটি পূর্ণ) ব্যবহার করতে পারেন।
ant2009

1
আমি এটি দরকারী খুঁজে পেয়েছি: gnu.org/software/gcc/bugs/segfault.html
সম্ভাব্যতা পছন্দ

2
btশর্টহ্যান্ড হিসাবে ব্যবহার করুন backtrace
rustyx

43

এছাড়াও, আপনি valgrindচেষ্টা করে দেখতে পারেন : যদি আপনি ইনস্টল করে valgrindচালনা করেন

valgrind --leak-check=full <program>

তারপরে এটি আপনার প্রোগ্রামটি চালাবে এবং যেকোন সিগফল্টের জন্য স্ট্যাকের চিহ্নগুলি প্রদর্শন করবে, পাশাপাশি কোনও অবৈধ মেমরি পড়বে বা লিখবে এবং মেমরি ফাঁস হবে। এটি সত্যিই বেশ দরকারী।


2
+1, ভ্যালগ্রাইন্ড মেমরির ত্রুটিগুলি স্পট করতে ব্যবহার করা এত দ্রুত / সহজ। নন-অপ্টিমাইজ করা ডিবাগ চিহ্ন দিয়ে তৈরী করে, এটা আপনাকে বলে ঠিক যেখানে একটি segfault ঘটেছে এবং কেন।
টিম পোস্ট

1
দুঃখের সাথে আমার সেগফল্টটি -g -O0 এর সাথে সংকলন এবং ভালগ্রাইন্ডের সাথে মিলিত হয়ে অদৃশ্য হয়ে যায়।
জনমুড

2
--leak-check=fullSegfaults ডিবাগ করতে সাহায্য করবে না। এটি কেবল মেমরি ফুটো ডিবাগ করার জন্য দরকারী।
ks1322

@ জনমুড আমার একটি সেগফল্ট রয়েছে কেবল পরীক্ষিত ইনপুট ফাইলের প্রায় 1% প্রদর্শিত, আপনি যদি ব্যর্থ ইনপুটটি পুনরাবৃত্তি করেন তবে এটি ব্যর্থ হবে না। আমার সমস্যা মাল্টিথ্রেডিংয়ের কারণে হয়েছিল। এখনও পর্যন্ত আমি এই সমস্যাটির কারণ হিসাবে কোডের লাইনটি বের করতে পারি নি। আমি আপাতত এই সমস্যাটি coverাকতে পুনরায় চেষ্টা করছি। -জি বিকল্প ব্যবহার করলে দোষ চলে যায়!
কেমিন ঝো

18

আপনি একটি কোর ডাম্প ব্যবহার করতে পারেন এবং তারপরে এটি জিডিবি দিয়ে পরীক্ষা করতে পারেন। দরকারী তথ্য পেতে আপনাকে -gপতাকা সহ সংকলন করতে হবে ।

আপনি যখনই বার্তাটি পাবেন:

 Segmentation fault (core dumped)

একটি কোর ফাইল আপনার বর্তমান ডিরেক্টরিতে লেখা আছে। এবং আপনি এটি কমান্ড দিয়ে পরীক্ষা করতে পারেন

 gdb your_program core_file

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

আপনার সিস্টেমটি কোর ডাম্প ফাইলের আকারটি শূন্যে সেট করে না তা নিশ্চিত করুন। আপনি এটি দিয়ে সীমাহীন এ সেট করতে পারেন:

ulimit -c unlimited

যত্নবান যদিও! যে কোর ডাম্পগুলি বিশাল আকার ধারণ করতে পারে।


আমি সম্প্রতি খিলান-লিনাক্সে স্যুইচ করেছি। আমার বর্তমান ডিরেক্টরিটিতে মূল ডাম্প ফাইল নেই। আমি কীভাবে এটি তৈরি করতে পারি?
অভিনব

আপনি এটি উত্পাদন করে না; লিনাক্স দেয়। কোর ডাম্পগুলি ডিফারেন্ট লিনুইস - গুগলের চারপাশে বিভিন্ন স্থানে সংরক্ষণ করা হয়। আর্ক লিনাক্সের জন্য, এই wiki.archlinux.org/index.php/Core_dump পড়ুন
মওগ বলেছেন মনিকা

7

এমন অনেকগুলি সরঞ্জাম উপলব্ধ রয়েছে যা বিভাগগুলি ত্রুটিগুলি ডিবাগ করতে সহায়তা করে এবং আমি আমার প্রিয় সরঞ্জামটি তালিকায় যুক্ত করতে চাই: ঠিকানা স্যানিটাইজারস (প্রায়শই এএসএন সংক্ষেপিত)

আধুনিক ¹ সংকলকগণ কার্যকর -fsanitize=addressপতাকা নিয়ে আসে , কিছু সংকলন সময় এবং রান টাইম ওভারহেড যুক্ত করে যা আরও ত্রুটি পরীক্ষা করে।

ডকুমেন্টেশন অনুসারে এই চেকগুলিতে ডিফল্টরূপে বিভাজন ত্রুটি ধরা include এখানে সুবিধাটি হ'ল আপনি জিডিবি'র আউটপুটের অনুরূপ স্ট্যাক ট্রেস পান, তবে কোনও ডিবাগারের ভিতরে প্রোগ্রামটি চালনা ছাড়াই। একটি উদাহরণ:

int main() {
  volatile int *ptr = (int*)0;
  *ptr = 0;
}
$ gcc -g -fsanitize=address main.c
$ ./a.out
AddressSanitizer:DEADLYSIGNAL
=================================================================
==4848==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x5654348db1a0 bp 0x7ffc05e39240 sp 0x7ffc05e39230 T0)
==4848==The signal is caused by a WRITE memory access.
==4848==Hint: address points to the zero page.
    #0 0x5654348db19f in main /tmp/tmp.s3gwjqb8zT/main.c:3
    #1 0x7f0e5a052b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)
    #2 0x5654348db099 in _start (/tmp/tmp.s3gwjqb8zT/a.out+0x1099)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /tmp/tmp.s3gwjqb8zT/main.c:3 in main
==4848==ABORTING

জিডিবি কি আউটপুট দেবে তার চেয়ে আউটপুট কিছুটা জটিল তবে আপসাইড রয়েছে:

  • স্ট্যাক ট্রেস পেতে সমস্যা পুনরুত্পাদন করার প্রয়োজন নেই। উন্নয়নের সময় কেবল পতাকা সক্ষম করা যথেষ্ট।

  • এএসএএনস কেবল বিভাজন ত্রুটিগুলি থেকে অনেক বেশি ধরা দেয়। সীমাবদ্ধ অ্যাক্সেসগুলির মধ্যে অনেকগুলি ধরা পড়বে এমনকি যদি সেই মেমরি অঞ্চলটি প্রক্রিয়াটিতে অ্যাক্সেসযোগ্য ছিল।


¹ এটি কলঙ্ক 3.1+ এবং জিসিসি 4.8+


এটি আমার পক্ষে সবচেয়ে সহায়ক। আমার খুব সূক্ষ্ম ত্রুটি রয়েছে যা প্রায় 1% ফ্রিকোয়েন্সি সহ এলোমেলোভাবে ঘটে থাকে। আমি প্রচুর সংখ্যক ইনপুট ফাইলগুলি (16 টি বড় পদক্ষেপ; প্রত্যেকটি আলাদা আলাদা আলাদা সি বা সি ++ বাইনারি দ্বারা সম্পন্ন) প্রসেস করি। একের পরের পদক্ষেপটি কেবলমাত্র বহু-থ্রেডিংয়ের কারণে এলোমেলোভাবে বিভাগগুলিকে ত্রুটিযুক্ত করবে। এটি ডিবাগ করা কঠিন। এই বিকল্পটি ডিবাগ তথ্য আউটপুটকে ট্রিগার করেছিল কমপক্ষে এটি আমাকে বাগ পর্যালোচনা করার জন্য কোড পর্যালোচনার জন্য একটি সূচনা পয়েন্ট দিয়েছে।
কেমিন ঝো

2

কোর ডাম্প সম্পর্কে লুকাসের উত্তর ভাল। আমার .cshrc এ আমার আছে:

alias core 'ls -lt core; echo where | gdb -core=core -silent; echo "\n"'

'কোর' প্রবেশ করে ব্যাকট্রেস প্রদর্শন করতে। এবং তারিখ স্ট্যাম্প, আমি সঠিক ফাইলটি খুঁজছি তা নিশ্চিত করার জন্য :(।

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


4
এবং ulimit -c unlimitedপ্রথম স্থানে কোর ডাম্প সক্ষম করতে ভুলবেন না ।
জেমস মরিস

@ জামেস: সঠিক। লুকাস ইতিমধ্যে এটি উল্লেখ করেছেন। এবং আমরা যারা এখনও csh- এ আটকে রয়েছি তাদের জন্য 'সীমাবদ্ধতা' ব্যবহার করুন। এবং আমি কখনই সিওয়ুইউইন স্ট্যাকডাম্পস পড়তে সক্ষম হইনি (তবে আমি 2 বা 3 বছর চেষ্টা করি নি)।
জোসেফ কুইনসে

2

উপরের সমস্ত উত্তর সঠিক এবং প্রস্তাবিত; এই উত্তরটি কেবলমাত্র একটি শেষ-অবলম্বন হিসাবে চিহ্নিত যদি উপরে বর্ণিত পদ্ধতির কোনওটি ব্যবহার করা না যায়।

অন্য সব কিছু যদি ব্যর্থ হয় তবে আপনি সর্বদা আপনার অ্যাক্সেসের fprintf(stderr, "CHECKPOINT REACHED @ %s:%i\n", __FILE__, __LINE__);প্রাসঙ্গিক অঙ্গ বলে মনে করেন এমন সমস্ত অস্থায়ী ডিবাগ-প্রিন্ট স্টেটমেন্ট (উদাহরণস্বরূপ ) দিয়ে আপনার প্রোগ্রামটি পুনরায় সংকলন করতে পারেন । তারপরে প্রোগ্রামটি চালান এবং ক্র্যাশ হওয়ার ঠিক আগে ডাব্ব-প্রিন্টটি কী ছাপা হয়েছিল তা পর্যালোচনা করুন - আপনি জানেন যে আপনার প্রোগ্রামটি এতদূর পেল, সুতরাং অবশ্যই ক্র্যাশটি ঘটেছে এই পয়েন্টের পরে। আপনি এটি কোনও কোডের একক লাইনে সংকীর্ণ না করা পর্যন্ত ডিবাগ-প্রিন্টগুলি যুক্ত করুন বা সরান, পুনরায় সংকলন করুন এবং আবার পরীক্ষা চালান। সেই সময়ে আপনি বাগটি ঠিক করতে এবং অস্থায়ী ডিবাগ-প্রিন্টগুলি সরাতে পারেন।

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

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