কোনও প্রক্রিয়া কখন স্যাব্যাবআরটি (সিগন্যাল)) পায়?


202

C ++ এ কোনও প্রক্রিয়া একটি SIGABRT পায় এমন পরিস্থিতিতে কী? এই সংকেতটি কি সর্বদা প্রক্রিয়াটির মধ্যে থেকে আসে বা এই প্রক্রিয়াটি একটি প্রক্রিয়া থেকে অন্য প্রক্রিয়ায় প্রেরণ করা যায়?

কোন প্রক্রিয়াটি এই সংকেতটি প্রেরণ করছে তা চিহ্নিত করার কোনও উপায় আছে?


3
কয়েকটি উপায় আছে। সবচেয়ে সহজ উপায়, যদি আপনি প্রোগ্রামটি লিখে থাকেন তবে তা হ'ল সিআইজিএবিআরটি-র জন্য একটি সিগন্যাল হ্যান্ডলার নিবন্ধন করা যা সেই তথ্যটি প্রিন্ট করে এবং ফিরে আসার আগে এর স্ট্রিমগুলি প্রবাহিত করে। দ্বিতীয় সহজ উপায় হ'ল স্ট্রেসের মধ্যে প্রোগ্রামটি চালানো। তৃতীয় সহজ উপায় হ'ল প্রোগ্রামটি ক্র্যাশ হওয়ার সাথে সাথে একটি মূল ফাইল তৈরি করে তা নিশ্চিত করা এবং মূল ডাম্পের মাধ্যমে এটি সন্ধান করা।
পার্থিয়ান শট

উত্তর:


194

abort()কলিং প্রক্রিয়াটি SIGABRTসিগন্যাল প্রেরণ করে , এভাবেইabort() মূলত কাজ করে।

abort()সাধারণত লাইব্রেরির ফাংশন দ্বারা ডাকা হয় যা কোনও অভ্যন্তরীণ ত্রুটি বা গুরুতরভাবে ভাঙা সীমাবদ্ধতা সনাক্ত করে। উদাহরণস্বরূপ malloc()কল করবে abort()যদি এর অভ্যন্তরীণ কাঠামোগুলি গাদা ওভারফ্লো দ্বারা ক্ষতিগ্রস্থ হয়।


27
আমার জন্য বেশিরভাগ ক্ষেত্রে libcfree()
সিএইসিএবিআরটি

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

2
ম্যাকোএসে, আমরা প্রায় 1000 ফাইল হ্যান্ডলগুলি বন্ধ না করে খোলার জন্য আমরা SIGABRT পেয়েছি। উপহাসের পরিবর্তে, আমাদের পরীক্ষাগুলি আরও জেনেরিক পাঠক প্রকারের সাথে ফাইলটিকে বিমূর্ত করে তোলে, যার কোনও Close()পদ্ধতি নেই, তাই এটি ভুলে গিয়েছিল। যদিও দুর্দান্ত কভারেজ ছিল। : রোলাইয়েস:
জিল

51

SIGABRTসমালোচনামূলক ত্রুটির ক্ষেত্রে প্রোগ্রামটি বাতিল করতে সাধারণত libc এবং অন্যান্য লাইব্রেরি দ্বারা ব্যবহৃত হয়। উদাহরণস্বরূপ, গ্লিব্যাক SIGABRTসনাক্ত করা ডাবল-ফ্রি বা অন্যান্য হিপ দূষিত হওয়ার ক্ষেত্রে প্রেরণ করে ।

এছাড়াও, বেশিরভাগ assertবাস্তবায়ন SIGABRTব্যর্থ দৃsert়তার ক্ষেত্রে ব্যবহার করে।

তদ্ব্যতীত, SIGABRTঅন্যান্য সিগন্যালের মতো অন্য যে কোনও প্রক্রিয়া থেকে পাঠানো যেতে পারে। অবশ্যই, প্রেরণ প্রক্রিয়া একই ব্যবহারকারী বা রুট হিসাবে চালানো প্রয়োজন।


49

আপনি kill(2)ইন্টারফেস ব্যবহার করে যে কোনও প্রক্রিয়াতে কোনও সংকেত পাঠাতে পারেন :

kill -SIGABRT 30823

30823 একটি dashপ্রক্রিয়া আমি শুরু করেছিলাম, তাই আমি যে প্রক্রিয়াটি হত্যা করতে চেয়েছিলাম তা সহজেই খুঁজে পেতে পারি।

$ /bin/dash
$ Aborted

Abortedআউটপুট দৃশ্যত কেমনdash একটি SIGABRT রিপোর্ট।

এটি ব্যবহার কোন প্রক্রিয়ায় সরাসরি পাঠানো যেতে পারে kill(2), অথবা একটি প্রক্রিয়া নিজেই সংকেত পাঠাতে পারেন মাধ্যমে assert(3), abort(3)অথবা raise(3)


17

মেমরি বরাদ্দ নিয়ে সমস্যা থাকলে সাধারণত এটি ঘটে।

আমার প্রোগ্রামটি যখন নেতিবাচক আকারের একটি অ্যারে বরাদ্দ করার চেষ্টা করছিল তখন আমার ক্ষেত্রে এটি ঘটেছিল।


14

সি ++ এর ক্ষেত্রে আরও একটি সাধারণ কারণ রয়েছে।

std::thread::~thread{
    if((joinable ())
        std::terminate ();
}

অর্থাত্ থ্রেডের স্কোপ শেষ হয়েছে তবে আপনি কোনও কল করতে ভুলে গেছেন

thread::join();

অথবা

thread::detach();

7

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

/ Dev / tty এর পরিবর্তে stdrr এ লেখার জন্য libc পুনঃনির্দেশের বিষয়ে আমার পোস্ট দেখুন:

Libc ত্রুটি বার্তাগুলি ক্যাচ করা, / dev / tty থেকে পুনর্নির্দেশ


4

প্রক্রিয়া যখন নিজের থেকে SIGABRT পায় তখন: হ্রভোজে একটি সমাধিস্থ হওয়া বিশুদ্ধ ভার্চুয়াল সম্পর্কে উল্লেখ করেছিলেন যে কর্টর থেকে একটি গর্ভপাত জেনারেট করা হয়েছিল, আমি এর জন্য একটি উদাহরণ তৈরি করেছি। এখানে যখন ডি নির্মাণ করা হবে, এটি প্রথমে তার বেস বর্গটিকে একটি কর্টর বলে এবং এটি পয়েন্টারের ভিতরে চলে যায়। টেবিলটি বৈধ পয়েন্টার দ্বারা ভরাট হওয়ার আগে একটি কর্টর বিশুদ্ধ ভার্চুয়াল পদ্ধতিটিকে কল করে, কারণ ডি এখনও নির্মিত হয়নি।

#include<iostream>
using namespace std;
class A {
public:
 A(A *pa){pa->f();}
 virtual void f()=0;
};
class D : public A {
public:
 D():A(this){}
 virtual void f() {cout<<"D::f\n";}
};
int main(){
 D d;
 A *pa = &d;
 pa->f();
 return 0;
}

সংকলন: g ++ -o aa aa.cpp

ulimit -c আনলিমিটেড

চালান: ./aa

pure virtual method called
terminate called without an active exception
Aborted (core dumped)

এখন আসুন দ্রুত মূল ফাইলটি দেখতে পেলাম এবং যাচাই করেছিলাম যে SIGABRT প্রকৃতপক্ষে বলা হয়েছিল:

gdb aa core

রেগস দেখুন:

i r
rdx            0x6      6
rsi            0x69a    1690
rdi            0x69a    1690
rip            0x7feae3170c37

চেক কোড:

ডিসস 0x7feae3170c37

mov    $0xea,%eax  = 234  <- this is the kill syscall, sends signal to process
syscall   <-----

http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

২৩৪ টি সিএস_টগকিল পিড_টি টিজিড পিড_টি পিড ইন্ট সিগ = = = সিগাব্যাট

:)


2

আমার ক্ষেত্রে এটি অ্যারের দৈর্ঘ্যের সমান সূচকটিতে অ্যারেতে ইনপুট দেওয়ার কারণে হয়েছিল।

string x[5];

for(int i=1; i<=5; i++){

    cin>>x[i];

}

x [5] অ্যাক্সেস করা হচ্ছে যা উপস্থিত নেই।


1

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

আমি যে সিস্টেমে কাজ করেছি তার একটির মধ্যে একটি ডেডলক ডিটেক্টর রয়েছে যা কার্যত হার্ট বিট দেয় বা না দিয়ে কোনও কাজ থেকে বেরিয়ে আসে কিনা তা সনাক্ত করে। যদি তা না হয় তবে এটি ঘোষণা করে যে প্রক্রিয়াটি অচল অবস্থায় রয়েছে এবং এতে SIGABORT প্রেরণ করে।

আমি কেবল জিজ্ঞাসা করা প্রশ্নের উল্লেখের সাথে এই সম্ভাব্যটি ভাগ করতে চেয়েছি।


0

আমি আমার উত্তরটি একটি প্রতিযোগিতামূলক প্রোগ্রামিং (সিপি) দৃষ্টিকোণ থেকে দেব , তবে এটি অন্যান্য ডোমেনগুলিতেও প্রযোজ্য।

সিপি করার সময় অনেক সময় সীমাবদ্ধতাগুলি বেশ বড়।

উদাহরণস্বরূপ : আমি একটি ভেরিয়েবল সাথে একটি প্রশ্ন ছিল N, M, Qযেমন যে 1 ≤ N, M, Q < 10^5

ভুল আমি তৈরি ছিল আমি আকার অ্যারে পূর্ণসংখ্যা একটি 2 ডি ঘোষণা করা হয় 10000 x 10000C++এবং সঙ্গে লড়াই SIGABRTপ্রায় 2 দিনের জন্য Codechef এ ত্রুটি।

এখন, যদি আমরা গণনা করি:

একটি পূর্ণসংখ্যার সাধারণ আকার: 4 বাইট

আমাদের অ্যারেতে কক্ষের সংখ্যা: 10000 x 10000

মোট আকার (বাইটে): 400000000 বাইট = 4 * 10 ^ 8 ≈ 400 এমবি

এই ধরণের প্রশ্নগুলির সমাধান আপনার পিসিতে কার্যকর হবে (সর্বদা নয়) কারণ এটি এই আকারটি বহন করতে পারে।

কোডিং সাইটগুলিতে (অনলাইন বিচারক) সংস্থানগুলি কয়েকটি কেবিতে সীমাবদ্ধ।

অতএব, SIGABRTত্রুটি এবং এই জাতীয় অন্যান্য ত্রুটি।

উপসংহার:

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

PS : এই ত্রুটির জন্য অন্যান্য কারণও থাকতে পারে; উপরে তাদের মধ্যে একটি ছিল।

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