第 11 章 动态内存分配
# 第 11 章 动态内存分配
书本内容
# 为什么使用动态内存分配
书本内容
# malloc
和 free
书本内容
# calloc
和 realloc
书本内容
# 使用动态分配的内存
书本内容
# 常见的动态内存错误
书本内容
# 内存分配实例
书本内容
# 总结
书本内容
# 问题
#
问题 1
- 静态声明的数组一般储存在栈中, 其具体的大小与栈的大小有关, unix 系统可以用
ulimit -a
进行查看- 限制的是字节数,具体的数组长度还跟数组储存的数据类型相关
- 参照 编程练习
- 动态内存所能获得的内存块的大小则主要与电脑内存的大小相关
#
问题 2
- 原题目翻译有问题, 应该是
- 如果每次请求分配 500 字节的内存时, 则你能获得的最大的动态内存数量是多少
答案
- 两种可能
- 一是请求较小的块时, 能分配更多的内存,
- 因为动态分配的是连续的内存块, 请求较小的块时, 最后剩下的内存块较小
- 二是请求较大的块, 能分配更多的内存
- 因为
malloc
需要储存额外的信息来跟踪所分配的内存块的信息- 比如内存的大小
- 所以, 请求较小的内存块时, 块的数量较多, 所需要的额外信息占用的内存较多
- 因为
- 一是请求较小的块时, 能分配更多的内存,
#
问题 3
答案
- 可以采用输出文本的编辑器所支持的最大行长度作为输入缓冲区的长度
#
问题 4
答案
- 主要优点是当分配内存的函数返回时, 这块内存会自动释放
- 可以保证不会出现内存泄漏
- 缺点
- 不能用来存储回传给调用程序的数据
- 其大小受系统堆栈大小的限制, 能分配的内存数量一般比
malloc
能分配的内存数量要小
#
问题 5
答案
- 应使用
sizeof(int)
来获取int
的所占用内存的大小 - 没有检查
malloc
的返回值是否为NULL
- 调整指针越过数组的左边界不符合标准的要求
- 调整指针后却没有从下标
1
处开始, 可能会破坏malloc
所使用的用于追踪堆的信息, 从而导致程序崩溃 - 没有检查输入值的范围, 非法输入值会导致程序崩溃
- 如果要返回数组, 则不应该使用
free(array)
#
问题 6
答案
- 动态分配可以减少堆栈的使用量, 因为动态分配的空间是从堆而不是从堆栈中获取的
- 对于标量数据,
- 如果是结构之类的大型数据, 可以使用动态内存分配
- 但如果只是简单的标量数据, 如整型, 则没有必要. 因为还需要分配一个指针用来指示动态内存的位置
#
问题 7
答案
- 可能会导致内存泄漏, 因为其内部的内存分配可能返回
NULL
# 编程练习
#
编程练习 1
答案
需要检查乘法是否溢出, 如果溢出, 则直接返回
NULL
代码
#include <stdlib.h> void *calloc(size_t num_elements, size_t element_size) { u_int64_t required_size = num_elements * (u_int64_t)element_size; size_t request_size = (size_t)required_size; if (request_size != required_size) return NULL; char *new_memory; new_memory = (char *)malloc(request_size); if (new_memory != NULL) { size_t i; char *ptr; for (i = 0; i < request_size; i++) *ptr++ = 0; } return new_memory; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
提示
#
编程练习 2
答案
代码
#include <stdio.h> #include <malloc.h> #define DELTA 8 int *readints() { int *array; int size; size = DELTA; array = (int *)malloc(size * sizeof(int)); if (array == NULL) return NULL; int value; int count; count = 0; while (scanf("%d", &value) == 1) { count++; if (count >= size) { size *= 2; array = (int *)realloc(array, size * sizeof(int)); if (array == NULL) return NULL; } array[count] = value; } if (count + 1 < size) { array = (int *)realloc(array, (count + 1) * sizeof(int)); if (array == NULL) return NULL; } array[0] = count; return array; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
提示
- 每次动态内存的数量递增 2 倍, 从概率上讲可以减少内存分配的次数
- 最后回收多分配的内存
#
编程练习 3
答案
代码
#include <stdio.h> #include <malloc.h> #define DELTA 8 char *readstring() { char *str; int size; int ch; int len; size = DELTA; str = (char *)malloc(size * sizeof(char)); if (str == NULL) return NULL; len = 0; do { ch = getchar(); if (ch == EOF || ch == '\n') ch = '\0'; str[len] = ch; len++; if (len > size) { size *= 2; str = (char *)realloc(str, size * sizeof(char)); if (str == NULL) return NULL; } } while (ch != '\0'); if (len < size) { str = (char *)realloc(str, (len + 1) * sizeof(char)); if (str == NULL) return NULL; } return str; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#
编程练习 4
答案
代码
#include <stdlib.h> #include <assert.h> typedef struct NODE { struct NODE *next; int value; } Node; Node *new_node(int value) { Node *node; node = (Node *)malloc(sizeof(Node)); assert(node != NULL); node->value = value; node->next = NULL; return node; } int main(void) { Node *head; head = new_node(5); head->next = new_node(10); head->next->next = new_node(15); free(head->next->next); free(head->next); free(head); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
编辑 (opens new window)
上次更新: 2022/01/26, 21:01:00