valgrind使用:检测非法读写内存
时间:2022-05-14
本文章向大家介绍valgrind使用:检测非法读写内存,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
14 Nov 2016 valgrind使用:检测非法读写内存
本文简单介绍如何通过valgrind检测c语言中的非法读写内存,避免发生不可预测行为。
1 什么非法读写内存
1.1 非法写内存
非法写内存是指往不属于程序分配的内存中写入数据。比如malloc一段内存,大小只有5个字节,那么你只能往这5个字节空间写入数据(如果是拷贝字符串,只能写4个字节),在这5字节的内存空间之外写入数据,都是非法的。比如写数组时越界,拷贝字符串时忘记结尾结束符。
1.2 非法读内存
非法读内存是指从不属于程序分配的内存读取数据。比如malloc一段内存,大小只有5个字节,并拷贝数据到该内存,大小刚好5个字节。但是在读取数据时,在这5字节的内存空间之外读取数据,都是非法的。类似的例子也是数组访问越界和字符串拷贝时忘记结束符占一个字节。
2 使用valgrind检测非法读写内存
示例代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
int index;
char *buffer = (char *)malloc(5);
strcpy(buffer, "01234");
for (index = 0; index < 5; ++index)
{
printf("buffer[%d] = %cn", index, buffer[index]);
}
printf("buffer[%d] = %cn", 5, buffer[5]);
printf("buffer[%d] = %cn", 6, buffer[6]);
free(buffer);
return 0;
}
2.1 程序输出
buffer[0] = 0
buffer[1] = 1
buffer[2] = 2
buffer[3] = 3
buffer[4] = 4
buffer[5] =
buffer[6] =
2.2 编译并使用valgrind检测非法读写内存
root@leo:demo# gcc -o valgrind_test_for_read_invalid_mem
valgrind_test_for_read_invalid_mem.c
root@leo:demo# valgrind --leak-check=full
./valgrind_test_for_read_invalid_mem 1 > valgrind_demo.log 2>&1
2.3 查看检测结果
root@leo:demo# cat valgrind_demo.log
==3879== Memcheck, a memory error detector
==3879== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3879== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==3879== Command: ./valgrind_test_for_read_invalid_mem 1
==3879==
==3879== Invalid write of size 2
==3879== at 0x4005DD: main (valgrind_test_for_read_invalid_mem.c:8)
==3879== Address 0x51fc044 is 4 bytes inside a block of size 5 alloc'd
==3879== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3879== by 0x4005CE: main (valgrind_test_for_read_invalid_mem.c:7)
==3879==
==3879== Invalid read of size 1
==3879== at 0x400625: main (valgrind_test_for_read_invalid_mem.c:15)
==3879== Address 0x51fc045 is 0 bytes after a block of size 5 alloc'd
==3879== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3879== by 0x4005CE: main (valgrind_test_for_read_invalid_mem.c:7)
==3879==
==3879== Invalid read of size 1
==3879== at 0x400649: main (valgrind_test_for_read_invalid_mem.c:16)
==3879== Address 0x51fc046 is 1 bytes after a block of size 5 alloc'd
==3879== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3879== by 0x4005CE: main (valgrind_test_for_read_invalid_mem.c:7)
==3879==
buffer[0] = 0
buffer[1] = 1
buffer[2] = 2
buffer[3] = 3
buffer[4] = 4
buffer[5] =
buffer[6] =
==3879==
==3879== HEAP SUMMARY:
==3879== in use at exit: 0 bytes in 0 blocks
==3879== total heap usage: 1 allocs, 1 frees, 5 bytes allocated
==3879==
==3879== All heap blocks were freed -- no leaks are possible
==3879==
==3879== For counts of detected and suppressed errors, rerun with: -v
==3879== ERROR SUMMARY: 4 errors from 3 contexts (suppressed: 0 from 0)
由日志可以看出,首先是非法写入了2个字节,因为分配了5个字节的内存,只能容纳下4个字符加上字符串结尾符,共5个字节,但是程序中拷贝了5个字节数据,加上字符串结尾符,共有6个字节。即非法写入了buffer[4]和buffer[5],因为buffer[4]应该是字符串结尾符,而buffer[5]不是程序分配的内存空间。其次,非法读取了2字节数据,即buffer[5]和buffer[6],程序只分配了5个字节,即buffer[0]-buffer[4],因此只能读取这5个字节内容。
本次荐书:数学之美
LEo at 21:47
- 常见.NET功能代码汇总 (2)
- 问题系列之Java中删除有序List的重复数据——提供两种方法
- 二叉树的基本概念和遍历
- Java中MD5加密算法实现方法——附上具体代码
- 新手,Visual Studio 2015 配置Boost库,如何编译和选择,遇到无法打开文件“libboost_thread-vc140-mt-gd-1_63.lib“的解决办法
- Java中处理正则表达式的工具类——总有一个适合你
- 【Spark研究】用Apache Spark进行大数据处理第一部分:入门介绍
- “一切都是消息”--MSF(消息服务框架)入门简介
- 【Spark研究】用Apache Spark进行大数据处理第二部分:Spark SQL
- Android基础总结(2)——活动Activity
- Java实现的IP处理工具类——可用于项目
- 使用SQLServer同义词和SQL邮件,解决发布订阅中订阅库丢失数据的问题
- 一次误报引发的DNS检测方案的思考:DNS隧道检测平民解决方案
- Andriod基础——Adapter类
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法