কোডটি কোথায় ভুল রয়েছে সে কারণে এটি কীভাবে নির্ধারণ করে যে সেগমেন্টেশন ত্রুটি সৃষ্টি করে ?
আমার সংকলক ( gcc
) প্রোগ্রামের ত্রুটির অবস্থানটি প্রদর্শন করতে পারে ?
কোডটি কোথায় ভুল রয়েছে সে কারণে এটি কীভাবে নির্ধারণ করে যে সেগমেন্টেশন ত্রুটি সৃষ্টি করে ?
আমার সংকলক ( gcc
) প্রোগ্রামের ত্রুটির অবস্থানটি প্রদর্শন করতে পারে ?
উত্তর:
জিসিসি এটি করতে পারে না তবে জিডিবি (একটি ডিবাগার ) নিশ্চিত করতে পারে। -g
স্যুইচটি ব্যবহার করে আপনি এই প্রোগ্রামটি সংকলন করুন :
gcc program.c -g
তারপরে জিডিবি ব্যবহার করুন:
$ gdb ./a.out
(gdb) run
<segfault happens here>
(gdb) backtrace
<offending code is shown here>
এখানেআপনাকে জিডিবি দিয়ে শুরু করার জন্য একটি দুর্দান্ত টিউটোরিয়াল ।
যেখানে সেগফল্ট হয় সাধারণত কোডের যেখানে এটি "ভুল যার কারণ হয়" তা কেবল একটি ক্লু থাকে। প্রদত্ত অবস্থানটি সমস্যাটি যেখানে থাকে তা অগত্যা নয়।
bt
শর্টহ্যান্ড হিসাবে ব্যবহার করুন backtrace
।
এছাড়াও, আপনি valgrind
চেষ্টা করে দেখতে পারেন : যদি আপনি ইনস্টল করে valgrind
চালনা করেন
valgrind --leak-check=full <program>
তারপরে এটি আপনার প্রোগ্রামটি চালাবে এবং যেকোন সিগফল্টের জন্য স্ট্যাকের চিহ্নগুলি প্রদর্শন করবে, পাশাপাশি কোনও অবৈধ মেমরি পড়বে বা লিখবে এবং মেমরি ফাঁস হবে। এটি সত্যিই বেশ দরকারী।
--leak-check=full
Segfaults ডিবাগ করতে সাহায্য করবে না। এটি কেবল মেমরি ফুটো ডিবাগ করার জন্য দরকারী।
আপনি একটি কোর ডাম্প ব্যবহার করতে পারেন এবং তারপরে এটি জিডিবি দিয়ে পরীক্ষা করতে পারেন। দরকারী তথ্য পেতে আপনাকে -g
পতাকা সহ সংকলন করতে হবে ।
আপনি যখনই বার্তাটি পাবেন:
Segmentation fault (core dumped)
একটি কোর ফাইল আপনার বর্তমান ডিরেক্টরিতে লেখা আছে। এবং আপনি এটি কমান্ড দিয়ে পরীক্ষা করতে পারেন
gdb your_program core_file
প্রোগ্রামটি ক্র্যাশ হওয়ার পরে ফাইলটিতে মেমরির অবস্থা রয়েছে। আপনার সফ্টওয়্যার স্থাপনের সময় একটি কোর ডাম্প কার্যকর হতে পারে।
আপনার সিস্টেমটি কোর ডাম্প ফাইলের আকারটি শূন্যে সেট করে না তা নিশ্চিত করুন। আপনি এটি দিয়ে সীমাহীন এ সেট করতে পারেন:
ulimit -c unlimited
যত্নবান যদিও! যে কোর ডাম্পগুলি বিশাল আকার ধারণ করতে পারে।
এমন অনেকগুলি সরঞ্জাম উপলব্ধ রয়েছে যা বিভাগগুলি ত্রুটিগুলি ডিবাগ করতে সহায়তা করে এবং আমি আমার প্রিয় সরঞ্জামটি তালিকায় যুক্ত করতে চাই: ঠিকানা স্যানিটাইজারস (প্রায়শই এএসএন সংক্ষেপিত) ।
আধুনিক ¹ সংকলকগণ কার্যকর -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+ ।
কোর ডাম্প সম্পর্কে লুকাসের উত্তর ভাল। আমার .cshrc এ আমার আছে:
alias core 'ls -lt core; echo where | gdb -core=core -silent; echo "\n"'
'কোর' প্রবেশ করে ব্যাকট্রেস প্রদর্শন করতে। এবং তারিখ স্ট্যাম্প, আমি সঠিক ফাইলটি খুঁজছি তা নিশ্চিত করার জন্য :(।
যোগ করা হয়েছে : যদি কোনও স্ট্যাক দুর্নীতির ত্রুটি থাকে তবে মূল ডাম্পের জন্য প্রয়োগ করা ব্যাকট্র্যাসটি প্রায়শই আবর্জনা। এক্ষেত্রে, জিডিবি-র মধ্যে প্রোগ্রামটি চালানো আরও ভাল ফলাফল দিতে পারে, গৃহীত উত্তর অনুসারে (দোষটি সহজেই পুনরায় উত্পাদনযোগ্য বলে ধরে নেওয়া যায়)) এবং একসাথে একাধিক প্রক্রিয়া ডাম্পিং কোর থেকে সাবধান; কিছু ওএস এর মূল ফাইলটির নামে পিআইডি যুক্ত করে।
ulimit -c unlimited
প্রথম স্থানে কোর ডাম্প সক্ষম করতে ভুলবেন না ।
উপরের সমস্ত উত্তর সঠিক এবং প্রস্তাবিত; এই উত্তরটি কেবলমাত্র একটি শেষ-অবলম্বন হিসাবে চিহ্নিত যদি উপরে বর্ণিত পদ্ধতির কোনওটি ব্যবহার করা না যায়।
অন্য সব কিছু যদি ব্যর্থ হয় তবে আপনি সর্বদা আপনার অ্যাক্সেসের fprintf(stderr, "CHECKPOINT REACHED @ %s:%i\n", __FILE__, __LINE__);
প্রাসঙ্গিক অঙ্গ বলে মনে করেন এমন সমস্ত অস্থায়ী ডিবাগ-প্রিন্ট স্টেটমেন্ট (উদাহরণস্বরূপ ) দিয়ে আপনার প্রোগ্রামটি পুনরায় সংকলন করতে পারেন । তারপরে প্রোগ্রামটি চালান এবং ক্র্যাশ হওয়ার ঠিক আগে ডাব্ব-প্রিন্টটি কী ছাপা হয়েছিল তা পর্যালোচনা করুন - আপনি জানেন যে আপনার প্রোগ্রামটি এতদূর পেল, সুতরাং অবশ্যই ক্র্যাশটি ঘটেছে এই পয়েন্টের পরে। আপনি এটি কোনও কোডের একক লাইনে সংকীর্ণ না করা পর্যন্ত ডিবাগ-প্রিন্টগুলি যুক্ত করুন বা সরান, পুনরায় সংকলন করুন এবং আবার পরীক্ষা চালান। সেই সময়ে আপনি বাগটি ঠিক করতে এবং অস্থায়ী ডিবাগ-প্রিন্টগুলি সরাতে পারেন।
এটি বেশ ক্লান্তিকর, তবে এটি যে কোনও জায়গায় কাজ করার সুবিধা রয়েছে - কেবলমাত্র যদি আপনি কোনও কারণে স্টাডাউট বা স্টাডারের অ্যাক্সেস না পেয়ে থাকেন, বা আপনি যে বাগটি ঠিক করতে চেষ্টা করছেন সেটি যদি একটি জাতি হয় তবে তা কেবলমাত্র তখনই না ঘটে -শক্তিটির প্রোগ্রামের সময় পরিবর্তন হওয়ার সাথে সাথে যার আচরণ পরিবর্তন হয় (যেহেতু ডিবাগ-প্রিন্টগুলি প্রোগ্রামটি ধীর করে দেয় এবং এর সময় পরিবর্তন করে)