好记性不如铅笔头

C && C++, 编程

一个简单的内存检测脚本

C语言编程中比较麻烦的就是内存问题,泄露,越界等,而且不好测试。如果是在嵌入式环境下,就更麻烦了,不好单步调试。这里作者笔记一个脚本,可以方便的测试出内存泄露。

CONTENTS

函数替换

首先根据自己的环境,替换下内存申请和释放函数

#if 1

typedef unsigned int MEM_UINT;
#define MEM_LOG printf
#define MEM_TEST_INT 0xABCDEF90

#define Malloc(SIZE_M) \
({ \
  int SIZE = SIZE_M; \
  char *tmp = malloc(sizeof(MEM_UINT) + SIZE + sizeof(MEM_UINT)); \
  *((MEM_UINT *)tmp) = (MEM_UINT)SIZE; \
  *((MEM_UINT *)(tmp + SIZE + sizeof(MEM_UINT))) = MEM_TEST_INT; \
  MEM_LOG("MEM_Malloc %x @%s:%d\r\n", (MEM_UINT)tmp, __FILE__,__LINE__);\
  (tmp + sizeof(MEM_UINT));\
})

#define Free(POINT_M) \
{\
    char *POINT = POINT_M;\
    if(POINT == NULL) \
    {MEM_LOG("MEM_Free_NULL @%s:%d \r\n", __FILE__,__LINE__);} \
    else \
    { \
        char *tmp = POINT - sizeof(MEM_UINT); \
        MEM_UINT size = *((MEM_UINT *)tmp); \
        MEM_UINT test_int = *((MEM_UINT *)(POINT + size)); \
        if(test_int != MEM_TEST_INT) \
        { \
            MEM_LOG("MEM_Over_Write %x %x-%x @%s:%d ", (MEM_UINT)tmp, test_int, MEM_TEST_INT, __FILE__,__LINE__);\
        }else \
        { \
            MEM_LOG("MEM_Free %x @%s:%d ", (MEM_UINT)tmp, __FILE__,__LINE__);\
        } \
        free(tmp); \
        MEM_LOG("SUCCESS\r\n");\
    } \
}

#else

#define  Malloc malloc
#define Free free

#endif

 Demo代码和输出

main.c

int main(int argc, char *argv[])
{
    char *pTest1 = Malloc(2);
    char *pTest2 = Malloc(3);
    char *pTest3 = Malloc(4);
    char *pTest4 = Malloc(5);

    Free(NULL);
    Free(pTest1);
    Free(pTest2);
    Free(pTest3);

    char *pTest = Malloc(10);
    pTest[10] = 3;
    Free(pTest);

    return 0;
}

输出

MEM_Malloc ba469010 @../MemLeakTest/main.c:51
MEM_Malloc ba469440 @../MemLeakTest/main.c:52
MEM_Malloc ba469460 @../MemLeakTest/main.c:53
MEM_Malloc ba469480 @../MemLeakTest/main.c:54
MEM_Free_NULL @../MemLeakTest/main.c:56 
MEM_Free ba469010 @../MemLeakTest/main.c:57 SUCCESS
MEM_Free ba469440 @../MemLeakTest/main.c:58 SUCCESS
MEM_Free ba469460 @../MemLeakTest/main.c:59 SUCCESS
MEM_Malloc ba469460 @../MemLeakTest/main.c:61
MEM_Over_Write ba469460 abcdef03-abcdef90 @../MemLeakTest/main.c:63 SUCCESS

内存分析

首先讲下面这份python代码保存,比如保存为MemAnalysis.py

#!/usr/bin/python3
# -*- coding: UTF-8 -*- 

malloc_dict = dict();
free_null_list = list();
over_write_list = list();

def handle_malloc_line(line_buf):
	buf_arr = line_buf.split(" ");
	if(buf_arr[1] in malloc_dict):
		print( "Addr:%d Malloced Before %s  %s\r\n"%(buf_arr[1], malloc_dict[ buf_arr[1] ], line_buf));
	else:
		malloc_dict[ buf_arr[1] ] = line_buf;

	return;


def handle_free_line(line_buf):
	buf_arr = line_buf.split(" ");
	if(buf_arr[1] in malloc_dict):
		del malloc_dict[buf_arr[1]];
	else:
		print( "Release MEM not Malloced %s"%(line_buf) );

	return;


def handle_free_null_line(line_buf):
	buf_arr = line_buf.split(" ");
	free_null_list.append( buf_arr[1] );

	return;


def handle_over_write_line(line_buf):
	handle_free_line(line_buf);
	over_write_list.append(line_buf);

	return;


def finish_log_handle():

	print("Free NULL:");
	for free_null in free_null_list:
		print(free_null);

	print("Over Write:");
	for over_write in over_write_list:
		print(over_write);

	mem_leak_keys = malloc_dict.keys();
	print("Mem Leak:");
	for mem_leak in mem_leak_keys:
		print(malloc_dict[mem_leak]);


	return;


analysis_dict = {
	"MEM_Malloc":handle_malloc_line,
	"MEM_Free":handle_free_line,
	"MEM_Free_NULL":handle_free_null_line,
	"MEM_Over_Write":handle_over_write_line
};


log_file = open("mem_test.log", "r");

while True:
	line_buf = log_file.readline();
	if not line_buf:
		break;

	parse_key_list = analysis_dict.keys();
	for parse_key in parse_key_list:
		start_with_parse_key = line_buf.startswith(parse_key);
		if(start_with_parse_key == True):
			parse_func = analysis_dict[parse_key];
			parse_func(line_buf);
			break;
		else:
			continue;

log_file.close();

finish_log_handle();

讲日志保存为mem_test.log,和python脚本放到同一目录下,然后执行命令:

$ python3 MemAnalysis.py 
Free NULL:
@../MemLeakTest/main.c:56
Over Write:
MEM_Over_Write ba469460 abcdef03-abcdef90 @../MemLeakTest/main.c:63 SUCCESS

Mem Leak:
MEM_Malloc ba469480 @../MemLeakTest/main.c:54

可以看到,内存泄露也越界都别识别出来了。

发表评论

20 + 4 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据