定位C程序内存错误
来源:互联网 发布:二手手机价格评估软件 编辑:程序博客网 时间:2024/06/06 03:26
这些信息是 ubuntu 7.10 , gcc 4.1.3, gdb 6.6-debian 跟踪的
当printf不够有效时。。。。
1。读懂错误信息
一个简单的例子;
#include <stdio.h>
#include <stdlib.h>
void a(){
char *s = "ee";
free(s);
}
int main(int argc, char **argv){
a();
return 1;
}
程序运行可以得到一下错误信息:
*** glibc detected *** ./r: free(): invalid pointer: 0x0804865c ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7e2dd65]
/lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7e31800]
./r[0x804838c]
./r[0x80483a4]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7dda050]
./r[0x8048311]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:05 1047431 /home/jing/Desktop/ee/r
08049000-0804a000 rw-p 00000000 08:05 1047431 /home/jing/Desktop/ee/r
0804a000-0806b000 rw-p 0804a000 00:00 0 [heap]
b7db8000-b7dc2000 r-xp 00000000 08:05 3499334 /lib/libgcc_s.so.1
b7dc2000-b7dc3000 rw-p 0000a000 08:05 3499334 /lib/libgcc_s.so.1
b7dc3000-b7dc4000 rw-p b7dc3000 00:00 0
b7dc4000-b7f08000 r-xp 00000000 08:05 3532035 /lib/tls/i686/cmov/libc-2.6.1.so
b7f08000-b7f09000 r--p 00143000 08:05 3532035 /lib/tls/i686/cmov/libc-2.6.1.so
b7f09000-b7f0b000 rw-p 00144000 08:05 3532035 /lib/tls/i686/cmov/libc-2.6.1.so
b7f0b000-b7f0e000 rw-p b7f0b000 00:00 0
b7f22000-b7f24000 rw-p b7f22000 00:00 0
b7f24000-b7f3e000 r-xp 00000000 08:05 3499469 /lib/ld-2.6.1.so
b7f3e000-b7f40000 rw-p 00019000 08:05 3499469 /lib/ld-2.6.1.so
bff2d000-bff42000 rw-p bff2d000 00:00 0 [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
Aborted (core dumped)
backtrace 提供函数的调用情况。
memroy map 是程序分配是虚拟内存的分配情况, 它的格式在各个操作系统下是不同的。 以上信息是linux下的运行。实际上输出的是/proc/pid/maps的信息。
(这个图在我的浏览器下显示不正常,可以点击memory map的连接查看源)
40049000-4035c000 r-xp 00000000 03:05 824473 /jdk1.5/jre/lib/i386/client/libjvm.so|<------------->| ^ ^ ^ ^ |<----------------------------------->| Memory region | | | | | | | | | | Permission --- + | | | | r: read | | | | w: write | | | | x: execute | | | | p: private | | | | s: share | | | | | | | | File offset ----------+ | | | | | | Major ID and minor ID of -------+ | | the device where the file | | is located (i.e. /dev/hda5) | | | | inode number ------------------------+ | | File name -------------------------------------------------------+
代码段(code segement)的权限是r-xp, 数据段(data segment)是rw-p
如果能马上明白错在哪里就好了, 如果不能马上找出错误, 就需要一些技巧快速找到问题的所在。
2. 找出出错的函数
链接程序时用到 -rdynamic 选项
gcc -g -o memleak memleak.c -rdynamic -ldl
-rdynamic
dlopen
-ldl 可以查看man dlopen (我不怎么明白这个dynamic linking 的实质.)
运行, 报错, 可以得到带符号表的信息:
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7dfed65]
/lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7e02800]
./r(a+0x18)[0x804859c]
./r(main+0x16)[0x80485b4]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7dab050]
从这里可以看出, a()的 free()调用错误了。
3. stack trace定位错误到行
如果一个函数被多次调用, 函数名就不足以区分到底是哪个调用出问题了。下面的方法可以试一下:
- 调用gdb调试
- 设置对出错函数的断点, 比如b free
- 到达断点后, 命令: bt, 查看函数调用情况, 就可以找出是哪个函数被调用, 直到找到出错的调用
* 把每一个函数检查一遍是很麻烦的, 可以捕捉系统发出的错误信号,
#include <stdlib.h>
#include <string.h>
#include <signal.h>
void a(){
char *s = "33";
char *d = NULL;
strcpy(d,s);
free(s);
return;
}
void sighandler(){
}
int main(int argc, char **argv){
signal(SIGSEGV, sighandler);
a();
return 1;
}
调试的时候, b sighandler, 然后bt.
但捕捉sigsegv是危险的,不能无限的捕捉, 不然无限循环了。捕捉一次就够。
5. 或者gdb下,在程序被强制退出后, 试一下list命令
6。工具:valgrind
内存差错的工具很多,valgrind是最强大的一个。有些工具提供一个库,连接到源代码,完了还要改回去,不方便。
有些工具检查一些特定的调用:
* strace: 系统调用, 比如文件打开,关闭
* mtrace, electronice fence(电网), dmalloc, MEMWATCH(mastering linux debugging techniques): malloc调用
* ltrace: "dynamic library call"
* nm, objdump: obj文件信息,信息太繁琐了, 也许要不得以而用之。 没有用过这两个工具。
7。其它
smash the stack
gcc与obj文件,动态链接文件和ELF文件
- 定位C程序内存错误
- BREW程序内存泄露定位
- VC程序错误定位方法
- Linux环境定位C程序内存泄露以及非法访问的方法
- 定位EXC_BAD_ACCESS错误和检查内存泄漏
- C内存错误
- C 内存错误
- 定位程序内存泄露的位置
- 内存错误(C/C++)
- 使用process monitor定位程序错误
- Ubuntu使用caore dump定位程序错误
- windows 程序异常崩溃等错误定位
- C程序内存分配
- C程序内存分布
- c程序内存分配
- c程序内存分布
- C 程序内存分配
- c程序内存布局
- C/C++学习笔记2 - cin深入分析(上) - cin输入操作处理(原创)
- C/C++学习笔记3 - cin深入分析(下) - cin的错误处理(原创)
- 广电为何退出手机电视标准评选
- Informix SQL函数的详细用法
- 关于绘图的效率
- 定位C程序内存错误
- BIRT 实现分页显示
- C语言中的内存分配深入(一)
- 开新空间啦!!
- 程序员每天该做的事
- 文本文件 二进制文件
- 用JFreeChart增强JSP报表的用户体验
- Service Broker 要点
- DotNet版的ExtJS单用户Blog系统源码解析