赞
踩
简单来说你 new 或者 malloc 一块内存后忘记 delete 或者 free 了,或者把地址丢失了导致无法进行释放。
以产生的方式来分类,内存泄漏可以分为四类:
常发性内存泄漏:发生内存泄漏的代码会被多次执行到,每次被执行时都会导致一块内存泄漏。
偶发性内存泄漏:发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
一次性内存泄漏:发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块且仅有一块内存发生泄漏。
隐式内存泄漏:程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到。
内存泄漏检查对于经常在 Windows 系统或者 Linux 系统下编程的人员来说会相对来说比较容易,有各种各样的工具能够用来检查内存泄漏,但对于嵌入式工程师来说就非常麻烦了,因为也没有什么工具能够检查。这里提供一个不需要依赖工具,只需要添加几个代码文件即可检查出哪里发生了内存泄漏的代码。
- #include "my_malloc.h"
-
- static MY_ITEM g_record[SIZE];//如果存在多线程的情况一定要注意互斥操作!!!
-
- void* my_malloc(size_t n, const char* file, const int line)
- {
- void* ret = malloc(n);
- if (ret != NULL)
- {
- int i = 0;
- for (i = 0; i < SIZE; i++)
- {
- if (g_record[i].pointer == NULL)
- {
- g_record[i].pointer = ret;
- g_record[i].size = n;
- g_record[i].file = file;
- g_record[i].line = line;
- break;
- }
- }
- }
- return ret;
- }
-
- void my_free(void* p)
- {
- if (p != NULL)
- {
- int i = 0;
- for (i = 0; i < SIZE; i++)
- {
- if (g_record[i].pointer == p)
- {
- g_record[i].pointer = NULL;
- g_record[i].size = 0;
- g_record[i].file = NULL;
- g_record[i].line = 0;
-
- free(p);
- break;
- }
- }
- }
- }
-
- void print_dynamic_memory_info(void)
- {
- int i = 0;
- printf("动态内存申请尚未释放的如下:\n");
- printf("%-20s\t%-10s\t%s\n", "地址", "地址大小", "申请位置");
-
- for (i = 0; i < SIZE; i++)
- {
- if (g_record[i].pointer != NULL)
- {
- printf("%-20p\t%-10d\t%s:%d 行\n",
- g_record[i].pointer, g_record[i].size, g_record[i].file, g_record[i].line);
- }
- }
- }
- #ifndef __MY_MALLOC_H__
- #define __MY_MALLOC_H__
-
- #include <stdio.h>
- #include <malloc.h>
-
- #define SIZE 256
-
- typedef struct
- {
- void* pointer;
- int size;
- const char* file;
- int line;
- }MY_ITEM;
-
- void* my_malloc(size_t n, const char* file, const int line);
- void my_free(void* p);
- void print_dynamic_memory_info(void);
-
- #endif // !__MY_MALLOC_H__
- #ifndef __MY_MALLOC_INF_H__
- #define __MY_MALLOC_INF_H__
-
- #include "my_malloc.h"
-
- #define malloc(n) my_malloc(n, __FILE__, __LINE__)
- #define free(p) my_free(p)
-
- //void* my_malloc(size_t n, const char* file, const int line);
- //void my_free(void* p);
-
- #endif // !__MY_MALLOC_INF_H__
只需将 #include "my_malloc_inf.h" 放到有动态申请内存的代码中即可(这同时也是它的不足之处)
比如在著名开源项目 cJSON.h 中添加进 #include "my_malloc_inf.h" 。
- #include <stdio.h>
- #include "my_malloc_inf.h"
- #include "cJSON.h"
-
- void main()
- {
- char* str = (char*)malloc(sizeof(char) * 6);
- cJSON* json = cJSON_CreateNull();
- print_dynamic_memory_info();
- cJSON_Delete(json);
- print_dynamic_memory_info();
- }
优点:
缺点:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。