第38课 动态内存分配

Posted wanmeishenghuo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第38课 动态内存分配相关的知识,希望对你有一定的参考价值。

动态内存分配的意义:

技术分享图片

 

malloc和free:

技术分享图片

 

 

技术分享图片

注意:

技术分享图片

 

思考:

malloc(0)将返回什么?

技术分享图片

 

运行结果如下:

技术分享图片

 

可以看到,返回了具体的地址。

我们所说的内存包括起始地址和长度。我们平时说内存的时候更多的是关注起始地址,而忽略了长度。

如果动态的综合这两部,我们使用malloc(0)返回了一个地址就不会奇怪了,因为这块内存的长度是0。这块内存我们可能无法正常使用,因为长度是0。

我们如果不停的malloc(0),会使系统的内存耗尽吗?

答案是会的,因为我们malloc的时候,得到的内存往往要比实际申请的大。

现在的内存申请一般都是四字节对齐的。

因此,malloc(0)也要使用free来释放这片内存。

 

 避免内存泄漏的内存泄漏检测模块:

mleak.h如下:

 1 #ifndef _MLEAK_H_
 2 #define _MLEAK_H_
 3 
 4 #include <malloc.h>
 5 
 6 #define MALLOC(n) mallocEx(n, __FILE__, __LINE__)
 7 #define FREE(p) freeEx(p)
 8 
 9 void* mallocEx(size_t n, const char* file, const line);
10 void freeEx(void* p);
11 void PRINT_LEAK_INFO();
12 
13 #endif

mleak.c如下:

 1 #include "mleak.h"
 2 
 3 #define SIZE 256
 4 
 5 /* 动态内存申请参数结构体 */
 6 typedef struct
 7 {
 8     void* pointer;
 9     int size;
10     const char* file;
11     int line;
12 } MItem;
13 
14 static MItem g_record[SIZE]; /* 记录动态内存申请的操作 */
15 
16 void* mallocEx(size_t n, const char* file, const line)
17 {
18     void* ret = malloc(n); /* 动态内存申请 */
19     
20     if( ret != NULL )
21     {
22         int i = 0;
23         
24         /* 遍历全局数组,记录此次操作 */
25         for(i=0; i<SIZE; i++)
26         {
27             /* 查找位置 */
28             if( g_record[i].pointer == NULL )
29             {
30                 g_record[i].pointer = ret;
31                 g_record[i].size = n;
32                 g_record[i].file = file;
33                 g_record[i].line = line;
34                 break;
35             }
36         }
37     }
38     
39     return ret;
40 }
41 
42 void freeEx(void* p)
43 {
44     if( p != NULL )
45     {
46         int i = 0;
47         
48         /* 遍历全局数组,释放内存空间,并清除操作记录 */
49         for(i=0; i<SIZE; i++)
50         {
51             if( g_record[i].pointer == p )
52             {
53                 g_record[i].pointer = NULL;
54                 g_record[i].size = 0;
55                 g_record[i].file = NULL;
56                 g_record[i].line = 0;
57                 
58                 free(p);
59                 
60                 break;
61             }
62         }
63     }
64 }
65 
66 void PRINT_LEAK_INFO()
67 {
68     int i = 0;
69     
70     printf("Potential Memory Leak Info:
");
71     
72     /* 遍历全局数组,打印未释放的空间记录 */
73     for(i=0; i<SIZE; i++)
74     {
75         if( g_record[i].pointer != NULL )
76         {
77             printf("Address: %p, size:%d, Location: %s:%d
", g_record[i].pointer, g_record[i].size, g_record[i].file, g_record[i].line);
78         }
79     }
80 }

主程序如下:

 1 #include <stdio.h>
 2 #include "mleak.h"
 3 
 4 void f()
 5 {
 6     MALLOC(100);
 7 }
 8 
 9 int main()
10 {
11     int* p = (int*)MALLOC(3 * sizeof(int));
12     
13     f();
14     
15     p[0] = 1;
16     p[1] = 2;
17     p[2] = 3;
18     
19     FREE(p);
20     
21     PRINT_LEAK_INFO();
22     
23     return 0;
24 }

运行结果如下:

技术分享图片

 

我们将第19行释放p的语句也注释掉,再次运次:

技术分享图片

 

calloc和realloc:

技术分享图片

 

示例程序:

 1 #include <stdio.h>
 2 #include <malloc.h>
 3 
 4 #define SIZE 5
 5 
 6 int main()
 7 {
 8     int i = 0;
 9     int* pI = (int*)malloc(SIZE * sizeof(int));
10     short* pS = (short*)calloc(SIZE, sizeof(short));
11     
12     for(i=0; i<SIZE; i++)
13     {
14         printf("pI[%d] = %d, pS[%d] = %d
", i, pI[i], i, pS[i]);
15     }
16     
17     printf("Before: pI = %p
", pI);
18     
19     pI = (int*)realloc(pI, 2 * SIZE * sizeof(int));
20     
21     printf("After: pI = %p
", pI);
22     
23     for(i=0; i<10; i++)
24     {
25         printf("pI[%d] = %d
", i, pI[i]);
26     }
27     
28     free(pI);
29     free(pS);
30     
31     return 0;
32 }

运行结果如下:

技术分享图片

 

bcc32的运行结果如下:

技术分享图片

 

vc编译器的结果如下;

技术分享图片

 

realloc重置之后地址值会发生变化。

可以得到结论:

calloc得到的内存是绝对会初始化的,malloc不会初始化。realloc会重置内存空间的大小,重置后扩大的内存部分可能是随机值。

 

小结:

技术分享图片

 

以上是关于第38课 动态内存分配的主要内容,如果未能解决你的问题,请参考以下文章

第55课 经典问题解析

动态内存分配php

第23课 优先选用make系列函数

第42课 内存操作经典问题分析二

类的 C++ 动态内存分配

第17课:Spark Streaming资源动态申请和动态控制消费速率原理剖析