4.15 常见内存错误及检测
1 常见内存错误
1.1 内存越界
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char *p = (char *)malloc(8);
strcpy(p,"hello world ! hello ubuntu!\n");
puts(p);
return 0;
}
1.2 内存踩踏
堆内存踩踏很难发现,常常不会发生 段错误(访问mmu管理的未授权的段)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char *p = (char *)malloc(8);
char *q = (char *)malloc(8); //q与p是紧挨着的
strcpy(p,"hello world ! hello ubuntu!\n");
puts(p);
puts(q); //q的内容被踩踏
return 0;
}
1.3 多次释放
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char *p = (char *)malloc(8);
free(p);
free(p);
return 0;
}
1.4 非法指针 (未初始化)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char *r;
*r = 1;
return 0;
}
2 使用valgrind内存检测
2.1 安装 valgrind 工具集
下载源文件
./configure
make
make install
valgrind --tool=memcheck ./a.out
2.2 工具集介绍
Memcheck:内存检测
Callgrind:程序性能分析、代码覆盖检测
Massif:堆栈分析器
Cachegrind:分析CPU的cache命中率、丢失率,用于代码优
例子
valgrind --version # 确认工具安装成功
gcc -g xxx.c #加上-g 选项,会保留代码的文字信息
valdrind --tool=memcheck ./a.out #使用 memcheck
valdrind --leak-check=full ./a.out #查看详细信息
3 内存检测memcheck
3.1 内存泄露检测
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char *p = (char *)malloc(8);
char *q = (char *)malloc(8);
free(p);
return 0;
}
3.2 内存覆盖检测
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char *p = (char *)malloc(8);
strcpy(p,"hello\n");
strcpy(p,p+1);
free(p);
return 0;
}
3.3 内存越界检测
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char *p = (char *)malloc(8);
char *q = (char *)malloc(8);
strcpy(p,"hello world ! hello ubuntu!\n");
free(p);
free(q);
return 0;
}