听说这段c++代码可以检测一些简单的内存越界

听说这段c++代码可以检测一些简单的内存越界,第1张

Class Base 是测试代码,检测内存越界的代码是下面这段代码

#define CHECKNU 6893\\除0外任意值;

#define PRECHECK_FIELD(i) int __precheck##i

#define POSCHECK_FIELD(i) int __poscheck##i

#define IN1T_CHECK(o,i){\

(o)->__precheck##i=CHECKNU\

(o)->__poscheck##i=CHECKNU\

}

#define CHECK(o,i){\

if((o)->__precheck##i!=CHECKNU ||(o)->__poscheck##i!=CHECKNU){\

printf("%s:%d,memory access out of range with checknu

pre %d,pos %d”,__FILE__,__LINE__,(o)->__precheck##i,(o)->__poscheck##i)\

}\

)

说一下他的思路,在每次申明内存块之前后各申明一个标志变量,并赋特毁乱腔定值陪拍,这样理论上在内存块里他们是连续的。看下面的语句

PRECHECK_FIELD(0)

char mem[1024]

POSCHECK_FIELD(0)

在每次使用自己定义的内存块mem前后,都检查一下,看之前定义的标志变量有没纤衫有被更改,如果有,则内存被越界 *** 作了。

MALLOC_CHECK_=0, 和没设置一样,将忽略这些错误 

MALLOC_CHECK_=1, 将打印一个错误告警 

MALLOC_CHECK_=2, 程序将收到SIGABRT信号退出

GNU C Library 可以根据环境变量MALLOC_CHECK_来决定是否在运行时可检测程序中的内存问题。而内存问题有时候表现得非常古怪,比如random crash, crash的点又经常变,甚至coredump中也没什么栈信息。这时候可以用这个方法来验证一下。知识还没办法打印出错点对应的地址,有些遗憾。

下面是一个内存越界的例子:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define BUF_SIZE 32

int main()

{

   伏指 int i

    char * buf1 = (char*) malloc(BUF_SIZE)

    printf("buf1: [%x] %p\禅厅拍n", buf1, buf1)

    memset(buf1, 'c', BUF_SIZE + 10)

    printf("%s:%d buf1: [%x]\n", __func__, __LINE__, buf1)

    free(buf1)

    char * buf = (char*) malloc(BUF_SIZE)

    printf("buf: [%x] %p\n", buf, buf)

    for (i = 0i <BUF_SIZEi++)

    {

        printf("%2x ", (0xFF &buf[i]))

    }

    free(buf)

    printf("\n")

    return 0

}

运行结果:

$ g++ test.cpp -o test

malloc: using debugging hooks

malloc: using debugging hooks

malloc: using debugging hooks

malloc: using debugging hooks

malloc: using debugging hooks

malloc: using debugging hooks

$ ./test

malloc: using debugging hooks

buf1: [9b7f050]

free(): invalid pointer 0x9b7f050!

malloc: top chunk is corrupt

buf: [9ba0008]

0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

$ export MALLOC_CHECK_=2

$ ./test

buf1: [a01d050]

Aborted

$ export MALLOC_CHECK_=0

$ ./test

buf1: [9e12050]

buf: [9e33008]

0   0   0   0   0   0  贺羡 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

$ unset MALLOC_CHECK_

$ ./test

buf1: [9062050]

buf: [9062050]

0   0   0   0 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63

[root@localhost malloc_check]# export MALLOC_CHECK_=1

[root@localhost malloc_check]# ./a.out

buf1: [216b010] 0x216b010

main:21 buf1: [216b010]

*** Error in `./a.out': free(): invalid pointer: 0x000000000216b010 ***

*** Error in `./a.out': malloc: top chunk is corrupt: 0x000000000216b030 ***

buf: [218c010] 0x218c010

0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

[root@localhost malloc_check]#

通过比较两次分配的指针地址可以看出,当使用MALLOC_CHECK_时,如果检测到memory corrupt时,有问题的memory将被特殊处理,而不是像正常情况一样被分配给新的request. 因此有可能出现使用了此环境变量之后,原本可能发生crash的程序反而工作正常了。

对于double free, 会给出类似下面的输出:

free(): invalid pointer 0x9186050!

遗憾的是此方法没能检测到读越界。

附info malloc 中对此环境变量的说明:

        Recent   versions   of   Linux libc (later than 5.4.23) and GNU libc (2.x)

        include a malloc implementation which is tunable via environment   vari-

        ables.   When MALLOC_CHECK_ is set, a special (less efficient) implemen-

        tation is used which is designed to be tolerant against simple   errors,

        such as double calls of free() with the same argument, or overruns of a

        single byte (off-by-one bugs).   Not all such errors   can   be   protected

        against, however, and memory leaks can result.   If MALLOC_CHECK_ is set

        to 0, any detected heap corruption is silently ignoredif set to 1,   a

        diagnostic is printed on stderrif set to 2, abort() is called immedi-

        ately.   This can be useful because otherwise a crash   may   happen   much

        later,   and   the   true cause for the problem is then very hard to track

首先,你的程序没有一个输出,是不可能有任何显示的

其次,你的程序就是一个死循环,同样不可能结束

最闷桥后,这里腔罩租的B[10]虽然越界了,但你给越界的内存地址伍兆又赋值的,因此A很自然的就等于你赋值的值,因为并没有越界检查所以不会报错

c你将它B+10的地址传给他,该地址的值为7,所以E也是同理

如果你的程序可以执行 正常情况下a=c=e=0XAA=170才对,不可能等于7


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12429122.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存