C语⾔:段错误产⽣原因及简单的调试⽅法段错误产⽣原因
1.访问不存在的内存地址
如下⾯代码,ptr没有申请空间就直接拷贝数据:
#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没有申请空间就直接使⽤
/
/The right way:
//ptr = (char *)malloc(sizeof(char) * 10);
//memset(ptr, 0, 10);
//strncpy(ptr, "abc", 3);
return 0;
}
2.访问只读的内存地址
错误做法:往字符串常量空间拷贝新的数据
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr = "test";
strcpy(ptr, "TEST1");
return 0;
}
3.访问系统保护的内存地址
如:
#include <stdio.h>
int main(int argc, char *argv[])
{
int *ptr = (int *)0;
include和contain*ptr = 100;
return 0;
}
4.栈溢出
如:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
main(argc, argv);
}
初学时两种常⽤的段错误调试⽅法
1.使⽤printf输出调试信息
这个是看似最简单但往往很多情况下是⼗分有效的调试⽅式,也许可以说是程序员⽤的最多的调试⽅式。简单来说,就是在程序的重要代码附近加上printf输出信息,这样可以跟踪并打印出段错误在代码中最可能出现的位置。
使⽤案例:
以下⾯这段错误代码为例:
#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没有申请空间就直接使⽤
return 0;
}
可以在代码中添加printf调试信息:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("line:%d\n", __LINE__); //单纯打印代码⾏数
char *ptr = NULL;
//This is the wrong implementation:
printf("line:%d\n", __LINE__); //单纯打印代码⾏数
strncpy(ptr, "abc", 3);//ptr没有申请空间就直接使⽤
printf("line:%d\n", __LINE__); //单纯打印代码⾏数
return 0;
}
编译运⾏后,会有如下输出:
line:7
line:10
Segmentation fault (core dumped)
通过⽇志信息,就可以看到strncpy(ptr, "abc", 3);语句没有被执⾏,我们就可以根据定位到的位置来排除ptr是否是未分配空间或者分配的空间不⾜引发的问题
2.使⽤gcc和gdb
调试步骤:
1、为了能够使⽤gdb调试程序,在编译阶段加上-g参数,还是以下⾯这段错误代码为例:
#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没有申请空间就直接使⽤
return 0;
}
编译代码添加-g选项
gcc -g -o test test.c
编译出test程序,然后⽤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 </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:
</software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
</software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./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没有申请空间就直接使⽤
(gdb) quit
A debugging session is active.
Inferior 1 [process 15829] will be killed.
Quit anyway? (y or n) y
从输出看出,程序到SIGSEGV信号,触发段错误,并提⽰地址0x0000555555554611以及代码第9⾏出错。
当然,还有利⽤core⽂件和gdb配置配合调试、使⽤objdump以及catchsegv命令的其他更为复杂的调试⼿段,这⾥就不展开讲。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。