linux下常见内存异常查证工具和方法介绍
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux下常见内存异常查证工具和方法介绍相关的知识,希望对你有一定的参考价值。
linux下常见内存异常查证工具和方法介绍
内存异常导致的异常往往很难查证,本文介绍在linux下的各种常见内存异常的查证工具和方法。
1、访问空指针/未初始化指针
这个是最简单的内存异常了,只要能够生成coredump文件,可以快速定位问题代码。
开启coredump
部分环境下默认不会生成coredump,需要运行如下命令:
ulimit -c unlimited //unlimited表示不限制coredump文件大小,也可以指定一个最大文件大小。
定制core文件名
默认的coredump文件名为core,如果想自己定制core文件名,可以运行如下命令:
echo “./core-%e-%p-%t” > /proc/sys/kernel/core_pattern
可以在core_pattern模板中使用变量还很多,见下面的列表:
%% 单个%字符
%p 所dump进程的进程ID
%u 所dump进程的实际用户ID
%g 所dump进程的实际组ID
%s 导致本次core dump的信号
%t core dump的时间 (由1970年1月1日计起的秒数)
%h 主机名
%e 程序文件名
使用gdb定位代码行
问题代码
int main()
{
int *p=0;
*p=6;
return 0;
}
使用gcc -g编译后运行出现异常,通过gdb即可定位出错代码行
[email protected]:/home/zte/test# gcc null.cc -g
[email protected]:/home/zte/test# ./a.out
Segmentation fault (core dumped)
[email protected]:/home/zte/test# gdb a.out core
.......
Core was generated by `./null‘.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00000000004004fd in main () at null.cc:4
4 *p=6;
2、函数栈溢出
局部变量的写越界可能会破坏函数栈帧导致程序coredump,由于默认不会在越界的第一现场coredump,导致问题查证非常困难。
幸运的是我们可以通过gcc的编译选项-fstack-protector 和 -fstack-protector-all在函数栈被破坏的第一现场就coredump,从而可以方便地定位问题。
示例
int main()
{
int a=5;
int *p=&a;
p[3]=6;
return 0;
}
上面代码会破坏函数栈,如果我们用gcc直接编译运行,不会抛异常。但是加了编译参数-fstack-protector 和 -fstack-protector-all后,再运行就会抛异常。下面是具体命令执行结果。
[email protected]:/home/zte/test# gcc t.c
[email protected]:/home/zte/test# ./a.out
[email protected]:/home/zte/test# gcc t.c -fstack-protector -fstack-protector-all -g
[email protected]:/home/zte/test# ./a.out
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)
可以进一步用gdb的bt命令定位出问题的函数。
[email protected]:/home/zte/test# gdb a.out core
。。。。。。。。
Core was generated by `./a.out‘.
Program terminated with signal SIGABRT, Aborted.
#0 0x00007f6bcfab5c37 in __GI_raise ([email protected]=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007f6bcfab5c37 in __GI_raise ([email protected]=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007f6bcfab9028 in __GI_abort () at abort.c:89
#2 0x00007f6bcfaf22a4 in __libc_message ([email protected]=1, [email protected]=0x7f6bcfc01d70 "*** %s ***: %s terminated\n")
at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007f6bcfb8d83c in __GI___fortify_fail (msg=<optimized out>, [email protected]=0x7f6bcfc01d58 "stack smashing detected")
at fortify_fail.c:38
#4 0x00007f6bcfb8d7e0 in __stack_chk_fail () at stack_chk_fail.c:28
#5 0x00000000004005aa in main () at t.c:7
(gdb) q
3、越界读写动态分配内存/读写已释放动态分配内存
动态分配内存读写越界、读写已释放动态分配内存系统默认可能不会抛异常,我们可以使用electric-fence来使得读写越界内存立刻抛异常,加速问题定位。
安装Electric fence
sudo apt-get install electric-fence
使用Electric fence
下面是越界写代码
#include <stdlib.h>
int main()
{
int *p = (int*)malloc(sizeof(int));
p[1] = 6;
return 0;
}
如果使用gcc直接编译运行,不会抛异常。
我们可以加上参数 -lefence -g编译后运行,就会抛异常。通过gdb的bt打印即可定位到问题代码行。
[email protected]:/home/zte/test# gcc malloc_read_free.cc -lefence -g
[email protected]:/home/zte/test# ./a.out
Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens <[email protected]>
Segmentation fault (core dumped)
4、动态分配内存重复释放
默认会抛异常,通过gdb和coredump即可定位。
generated by haroopad本文出自 “邬领东的博客” 博客,请务必保留此出处http://13484557.blog.51cto.com/13474557/1983537
以上是关于linux下常见内存异常查证工具和方法介绍的主要内容,如果未能解决你的问题,请参考以下文章