आपका कोड इसे पकड़ने के बजाय SIGSEGV को अनदेखा कर रहा है। याद रखें कि सिग्नल को संभालने के बाद सिग्नल ट्रिगर करने वाले निर्देश को पुनरारंभ किया जाता है। आपके मामले में, सिग्नल को संभालने से कुछ भी नहीं बदला गया है, अगली बार अपमानजनक निर्देश के चारों ओर प्रयास करने की कोशिश की जाती है, यह उसी तरह विफल हो जाती है।
आप इस
signal(SIGSEGV, sighandler);
के संकेत परिवर्तन को पकड़ने के लिए इस
signal(SIGSEGV, SIG_IGN);
इरादा है आप शायद भी sigaction()
बजाय signal()
उपयोग करना चाहिए। प्रासंगिक मैन पेज देखें।
आपके मामले में अपमानजनक निर्देश वह है जो नल पॉइंटर को कम करने की कोशिश करता है।
printf("%d", *p);
आपके प्लेटफ़ॉर्म पर पूरी तरह से निर्भर है।
आप gdb
का उपयोग यह निर्धारित करने के लिए कर सकते हैं कि कौन सा विशेष असेंबली निर्देश संकेत को ट्रिगर करता है।अपने मंच मेरा ऐसा कुछ है, तो आप पाएंगे अनुदेश Rax रजिस्टर मान 0 पकड़े, अर्थात NULL
साथ
movl (%rax), %esi
है। आपके सिग्नल हैंडलर में इसे ठीक करने के लिए एक (गैर-पोर्टेबल!) तरीका है कि आपके हैंडलर को तीसरे तर्क संकेत का उपयोग करना है, यानी उपयोगकर्ता संदर्भ।
#include <signal.h>
#include <stdio.h>
#define __USE_GNU
#include <ucontext.h>
int *p = NULL;
int n = 100;
void sighandler(int signo, siginfo_t *si, ucontext_t* context)
{
printf("Handler executed for signal %d\n", signo);
context->uc_mcontext.gregs[REG_RAX] = &n;
}
int main(int argc,char ** argv)
{
signal(SIGSEGV, sighandler);
printf("%d\n", *p); // ... movl (%rax), %esi ...
return 0;
}
इस कार्यक्रम को प्रदर्शित करता है:
Handler executed for signal 11
100
यह पहली बार का कारण बनता है हैंडलर एक शून्य पते भिन्नता के प्रयास के द्वारा निष्पादित किया जाना है यहाँ एक उदाहरण है। फिर हैंडलर n
के पते पर रैक्स सेट करके समस्या को हल करता है। एक बार हैंडलर लौटने के बाद सिस्टम अपमानजनक निर्देश को पुनः प्राप्त करता है और इस बार सफल होता है। printf()
अपने दूसरे तर्क के रूप में 100 प्राप्त करता है।
हालांकि, मैं आपके कार्यक्रमों में ऐसे गैर-पोर्टेबल समाधानों का उपयोग करने की दृढ़ता से अनुशंसा करता हूं।
एक ऐसा समय होगा जिसमें सेगफाल्ट निगलने वाले लेखन कोड को प्रोग्रामर को जेल में रखने के लिए पर्याप्त माना जाएगा। – 6502