Causes of segment errors and simple debugging methods

Reference: section error causes and simple debugging methods
Author: those years of programming
website: https://mp.weixin.qq.com/s/KP9ZFn71CO_vB2I4igZLMA

Cause of segment error

1. Access non-existent memory address

As shown in the following code, ptr directly copies data without applying for space:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
   char *ptr = NULL;
   //This is the wrong implementation: 
   strncpy(ptr, "abc", 3);//ptr can be used directly without application space

   //The right way:
   //ptr = (char *)malloc(sizeof(char) * 10);
   //memset(ptr, 0, 10);
   //strncpy(ptr, "abc", 3);

   return 0;
}

2. Access the read-only memory address

Wrong practice: copy new data into the string constant space

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *ptr = "test";
    strcpy(ptr, "TEST1");

    return 0;
}

3. Access the memory address protected by the system

For example:

#include <stdio.h>

int main(int argc, char *argv[])
{
    int *ptr = (int *)0;
    *ptr = 100;

    return 0;
}

4. Stack overflow

For example:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    main(argc, argv);
}

Two commonly used debugging methods of segment errors in beginner's learning

1. Use printf to output debugging information

This seems to be the simplest but often very effective debugging method in many cases. It may be said that it is the most used debugging method by programmers. Simply put, it is to add printf output information near the important code of the program, so that you can track and print out the most likely location of a segment of error in the code.

Use case:
Take the following error code as an example:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
   char *ptr = NULL;
   //This is the wrong implementation: 
   strncpy(ptr, "abc", 3);//ptr can be used directly without application space

   return 0;
}

printf debugging information can be added to the code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    printf("line:%d\n", __LINE__); //Number of lines of code printed only
   char *ptr = NULL;
   //This is the wrong implementation: 
   printf("line:%d\n", __LINE__); //Number of lines of code printed only
   strncpy(ptr, "abc", 3);//ptr can be used directly without application space
    printf("line:%d\n", __LINE__); //Number of lines of code printed only

   return 0;
}

After compiling and running, the following output will be generated:

line:7
line:10
Segmentation fault (core dumped)

Through the log information, you can see strncpy(ptr, "abc", 3); If the statement is not executed, we can rule out whether ptr is caused by unallocated space or insufficient allocated space according to the location

2. Use gcc and gdb

Commissioning steps:

1. In order to use the gdb debugger, add the - g parameter at the compilation stage, or take the following error code as an example:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
   char *ptr = NULL;
   //This is the wrong implementation: 
   strncpy(ptr, "abc", 3);//ptr can be used directly without application space

   return 0;
}

Add - g option to compile code

gcc -g -o test test.c

Compile the test program and debug it with gdb:

linux@linux:~/test$ gdb ./test
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test...done.
(gdb) r
Starting program: /home/linux/test/test 

Program received signal SIGSEGV, Segmentation fault.
0x0000555555554611 in main (argc=1, argv=0x7fffffffe528) at test.c:9
9                               strncpy(ptr, "abc", 3);//ptr can be used directly without application space
(gdb) quit
A debugging session is active.

        Inferior 1 [process 15829] will be killed.

Quit anyway? (y or n) y

It can be seen from the output that when the program receives SIGSEGV signal, it triggers segment error, and prompts address 0x000055554611 and error on line 9 of the code.

Of course, there are other more complex debugging methods that use core files and gdb configuration to cooperate with debugging, objdump and catchsegv commands, which will not be discussed here.

Posted by Toshiba23 on Sun, 31 Oct 2021 00:13:46 -0700