Make mistakes is no longer an error

Today's theme is: a visit to a certain segment null pointer error (segmentation fault) will do?

Look at the code below:
test.c

#include <stdio.h>

int main()
{
    int *p = NULL;

    *p = 1;

    return 0;
}

In Linux inside to write so much code, it should be very clear, the above code segment error, because a visit to a null pointer.

#gcc test.c -o test
#./test
Segmentation fault
#

Phenomenon and we think the same. In Linux, a null pointer if the visit or field guide, there will be mistakes (segmentation fault), which is the operating system for the protection of memory. When mistakes occur, the system will send a signal 11 (SIGSEGV), this signal is received, the program hung up. Let's verify:

circle.c

#include <stdio.h>

int main()
{
    while (1);

    return 0;
}

Is a simple infinite loop program up and running, and then open a terminal, the first query process pid, sending a SIGSEGV signal and then kill:

Here Insert Picture Description
Then look at the results of running the program:

Here Insert Picture DescriptionClearly not the same phenomenon occurs and the program segment error phenomenon.

It is well known in the Linux inside, the process of processing of the signal There are three ways to capture ignored, the default behavior. Under normal circumstances, you do nothing, that is, the default behavior, such as CTRL + C will let the process die.

But after the following process, CTRL + C is not only die, but also to print things:

signal.c

#include <stdio.h>
#include <signal.h>

void handler(int sig)
{
    printf("receive signal %d\n", sig);
}

int main()
{
    signal(SIGINT, handler);

    while (1);

    return 0;
}

Compile and run, then keep hitting CTRL + C:

Here Insert Picture Description
The reason is simple, the process SIGINT signal No. 2 is that we captured. This from the ps command which can also be seen (note CAUGHT this column):

Here Insert Picture Description
Of course, we can choose to ignore it:

#include <stdio.h>
#include <signal.h>

int main()
{
    signal(SIGINT, SIG_IGN);

    while (1);

    return 0;
}

No matter how pressing CTRL + C, of ​​no use:

Here Insert Picture Description
We can still look at ps (note IGNORED this column):

Here Insert Picture DescriptionIn so many signals which, in addition to a handful of similar signal SIGKILL, SIGSTOP can not capture this and ignore outside, the other is can be used to play with us, of course, including SIGSEGV segment error (No. 11 looks Niubi roaring )signal of.

I have repeatedly stressed that, when you use the CTRL + C and other signals corresponding to kill a process when A, you never kill A, but you sent a signal to the A and A in response to this signal when the corresponding behavior is the process exit. So it is not a process you kill A, but you send a signal, "notice" A target process to die. So you can not kill the human world to understand Linux kill. Linux's similar logic: You're right process A: "You go to hell" (it can send a signal to die), A pending signal after seeing this, what nonsense do not say, immediately muffled be dead! So, you just change the response behavior of A, you can choose to die.

Here the problem is simple, we continue to make use of setjmp and longjmp to implement a segmentation fault:

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

jmp_buf env;

void handler(int sig)
{
    longjmp(env, 1);         //跳转到上一次保存的现场
}

int main()
{
    int ret = setjmp(env);   //保存执行现场,返回0
    if (0 == ret)
    {   
        signal(SIGSEGV, handler);

        printf("制造段错误...\n");
        int *p = NULL;
        *p = 1;
    }   
    else
    {   
        printf("段错误后!\n");
    }

    return 0;
}

The principle of this function setjmp is:

Call this function when it saves the execution site, and return 0; After calling longjmp, setjmp be restored to save the site, setjmp returns again, but this time returns longjmp () is the second parameter. Look at the following chart:

Here Insert Picture Description
If we slightly modified the code, delete the line:

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

jmp_buf env;

void handler(int sig)
{
    longjmp(env, 1);         //跳转到上一次保存的现场
}

int main()
{
    int ret = setjmp(env);   //保存执行现场,返回0
    if (0 == ret)
    {   
        //signal(SIGSEGV, handler);

        printf("制造段错误...\n");
        int *p = NULL;
        *p = 1;
    }   
    else
    {   
        printf("段错误后!\n");
    }

    return 0;
}

Phenomenon is familiar to us:

Here Insert Picture Description
Did not understand, an error signal segment is only to protect the operating system memory issued, the process receives a signal default processing to hang up, so in order to avoid mistakes, ignoring SIGSEGV on the line. Of course, this is absolutely the last resort, use this method to fix mistakes is simply silent, more important still write code memory usage when the attention, do not access the memory can not be accessed.

For more articles, videos, embedded learning materials, micro-channel public concern number "have learned the benefits of intelligent hardware."

Here Insert Picture Description

Published 12 original articles · won praise 24 · views 2436

Guess you like

Origin blog.csdn.net/xiaopengX6/article/details/104596666