"Segmentation fault(段错误)"探究

本文深入探讨了Segmentation fault(段错误)的常见原因,包括向受保护内存地址写入数据和内存越界。通过实例代码和GDB调试,详细解释了如何定位和解决这类错误。示例中,由于使用strcat函数时未正确分配内存导致内存溢出,从而引发了段错误。建议在使用类似函数时确保目标内存空间足够大,以避免段错误的发生。
摘要由CSDN通过智能技术生成

在rhel5.4上用GCC编程好长时间了(其实也就1个多月!),经常遇到这种情况:一个程序编译没有任何问题,当执行

./a.out的时候出现:“Segmentation fault(段错误)”,下面就是最近的一次情况(目的只是测试strcat函数):

      #include<stdio.h>
 25 #include<string.h>
 26 int main()
 27 {
 28         char *str1 = "Wang";
 29         char *str2 = "Lei";
 30         printf("%s/n", strcat(str1, str2));
 31         return 0;
 32 }
(前面的数字只是标号,不是程序部分)。

编译运行:

[root@localhost C]# cc my_strcat.c
[root@localhost C]# ./a.out
Segmentation fault
于是开始查找信息,下面是查找的情况。(我把上面代码的调试放在了最后!是一个内存溢出的错误!)

 

=======================>8====================================================

(没经作者容许就剪贴过来了,在此表示歉意!)

1)往受到系统保护的内存地址写数据

有些内存是内核占用的或者是其他程序正在使用,为了保证系统正常工作,所以会受到系统的保护,而不能任意访问.

#include <stdio.h>

int
main()
{
int i = 0;

scanf ("%d", i); /* should have used &i */
printf ("%d/n", i);
return 0;
}

编译和执行一下, 咋一看,好像没有问题哦,不就是读取一个数据然后给输出来吗?

falcon@falcon:~/temp$ gcc -g -o segerr segerr.c –加-g选项查看调试信息
falcon@falcon:~/temp$ gdb ./segerr
GNU gdb 6.4-debian
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB. Type “show warranty” for details.
This GDB was configured as “i486-linux-gnu”…Using host libthread_db library “/ lib/tls/i686/cmov/libthread_db.so.1″.

(gdb) l –用l(list)显示我们的源代码
1 #include <stdio.h>
2
3 int
4 main()
5 {
6 int i = 0;
7
8 scanf (”%d”, i); /* should have used &i */
9 printf (”%d/n”, i);
10 return 0;
(gdb) b 8 –用b(break)设置断点
Breakpoint 1 at 0×80483b7: file segerr.c, line 8.
(gdb) p i –用p(print)打印变量i的值[看到没,这里i的值是0哦]
$1 = 0

(gdb) r –用r(run)运行,直到断点处
Starting program: /home/falcon/temp/segerr

Breakpoint 1, main () at segerr.c:8
8 scanf (”%d”, i); /* should have used &i */ –[试图往地址0处写进一个值]
(gdb) n –用n(next)执行下一步
10

Program received signal SIGSEGV, Segmentation fault.
0xb7e9a1ca in _IO_vfscanf () from /lib/tls/i686/cmov/libc.so.6
(gdb) c –在上面我们接收到了SIGSEGV,然后用c(continue)继续执行
Continuing.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) quit –退出gdb

果然
我们“不小心”把&i写成了i
而我们刚开始初始化了i为0,这样我们不是试图向内存地址0存放一个值吗?

[补充:
可以通过man 7 signal查看SIGSEGV的信息。

falcon@falcon:~/temp$ man 7 signal | grep SEGV
Reformatting signal(7), please wait…
SIGSEGV 11 Core Invalid memory reference

例子2:

#include <stdio.h>
int
main()
{
char *p;

p = NULL;

*p = ‘x’;

printf(”%c”, *p);
return 0;
}
很容易发现,这个例子也是试图往内存地址0处写东西。

这里我们通过gdb来查看段错误所在的行

falcon@falcon:~/temp$ gcc -g -o segerr segerr.c
falcon@falcon:~/temp$ gdb ./segerr
GNU gdb 6.4-debian
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB. Type “show warranty” for details.
This GDB was configured as “i486-linux-gnu”…Using host libthread_db library “/lib/tls/i686/cmov/libthread_db.so.1″.

(gdb) r –直接运行,我们看到抛出段错误以后,自动显示出了出现段错误的行,这就是一个找出段错误的方法
Starting program: /home/falcon/temp/segerr

Program received signal SIGSEGV, Segmentation fault.
0×08048516 in main () at segerr.c:10
10 *p = ‘x’;
(gdb)

2)内存越界(数组越界

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值