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] = %c\n", index, buffer[index]);
    }

    printf("buffer[%d] = %c\n", 5, buffer[5]);
    printf("buffer[%d] = %c\n", 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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏wOw的Android小站

[Objective-C] 常量和枚举

#define宏定义 #define是一条预编译指令, 编译器在编译阶段前期会将所有使用到宏的地方简单地进行替换.

9820
来自专栏猿人谷

PHP常用库函数介绍+常见疑难问题解答

      最近在苦学PHP,虽然PHP在整体功能上不如Java强大,但相比PHP而言Java算是较重量级的,所以在小中型系统的开发上,使用PHP的趋势不可挡,...

22880
来自专栏编程

《5》python字符串和编码

「5」python字符串和编码 ? 字符编码 最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大...

207100
来自专栏Laoqi's Linux运维专列

函数的参数

14470
来自专栏用户2442861的专栏

Python yield 使用浅析

您可能听说过,带有 yield 的函数在 Python 中被称之为 generator(生成器),何谓 generator ?

9910
来自专栏潇涧技术专栏

Python Basics

1.使用glob模块可以用通配符的方式搜索某个目录下的特定文件,返回结果是一个list

10620
来自专栏小樱的经验随笔

getline函数(精华版)

在我的印象中,getline函数经常出现在自己的视野里,模糊地记得它经常用来读取字符串 。但是又对它的参数不是很了解,今天又用到了getline函数,现在来细细...

39840
来自专栏偏前端工程师的驿站

JS魔法堂:ES6新特性——GeneratorFunction介绍

一、前言                                   第一次看koajs的示例时,发现该语句 function *(next){.....

27650
来自专栏我是攻城师

理解Java集合框架里面的的transient关键字

37980
来自专栏yang0range

Java的面试基础题(二)

1)特点:存储对象;长度可变;存储对象的类型可不同 2)Collection (1)List:有序的;元素可重复,有索引 (add(index, elem...

19920

扫码关注云+社区

领取腾讯云代金券