知识点回顾
1. 动态内存管理的几个函数
malloc -- 申请动态内存空间
free -- 释放动态内存空间
calloc -- 申请并初始化一系列内存空间
realloc -- 重新分配内存空间
2. 内存泄漏
导致内存泄漏主要有两种情况:
隐式内存泄漏(即用完内存块没有及时使用free函数释放)
丢失内存块地址
测试题
*0. 你看过 malloc 函数的原型是这样的 void malloc(size_t size);,那你知道 size_t 实际上是什么类型吗?
答:应该是整型。
正解:size_t 实际上就是 unsigned int(无符号整型),在 64 位系统中是被定义为 long unsigned int
1. 你知道 C 语言动态内存管理中最令人切齿痛恨的是什么吗?
答:没有垃圾回收机制,每次申请完内存。都要手动释放内存。
正解:使用 malloc 申请了内存空间,但用完之后没有用 free 及时释放空间。这就好比你家开了餐馆,但大家上厕所永远都不冲水那样让人讨厌。
2. 下面代码中,如果第一行打印的是“Before free, ptr = 0x8b23008”,请问第二行打印的是什么?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *ptr = NULL;
ptr = (int *)malloc(sizeof(int));
if (ptr == NULL)
{
printf("内存分配失败!\n");
exit(1);
}
printf("Before free, ptr = %p\n", ptr);
free(ptr);
printf("After free, ptr = %p\n", ptr);
return 0;
}
答:After free,ptr = 0x8b23008;
有鱼油可能会疑惑:”难道调用 free() 函数释放内存后,ptr 不是应该指向 NULL 的吗?“。这里务必要注意一点,free() 函数释放的是 ptr 指向的内存空间,但它并不会修改 ptr 指针的值。也就是说,ptr 现在虽然指向 0x8b23008,但该空间已经被 free() 函数释放了,所以对于该空间的引用已经失去了意义(会报错)。因此,为了防止后面再次对 ptr 指向的空间进行访问,建议在调用 free() 函数后随即将 ptr 赋值为 NULL。
3. 请问下面划红线位置应该填什么?
char (*str)[1024];
str = ( ~~~~~~~~ )malloc(1024);
答:应该写char *。
- 下面代码统计了程序在崩溃前一共调用了多少次 malloc(1024):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t count = 0;
while (1)
{
malloc(1024);
printf("%u\n", count++);
}
}
答:电脑可运行内存除以1024次。
小甲鱼说他运行了一定的次数被系统killed了,增加粒度到101024反而在无限循环。而我实测结果是粒度为1024、101024、1001024都是无限循环,而粒度为10001024时电脑立即崩溃哦。
这是为什么呢?
正解:答:因为将每次申请堆内存空间的粒度调大,malloc 函数会直接返回 NULL 表示失败,这样程序既不会因为内存耗尽而崩溃,也不会退出死循环……
动动手
0. 编写一个程序,让用户决定要录入的整数个数,然后再申请相应的内存空间来存放(要求使用 malloc 函数来申请内存空间)。
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int num, i;
printf("请输入待录入的整数个数:");
scanf("%d",&num);
int *ptr = (int *)malloc(sizeof(int) * num);
for (i = 0; i < num; i++)
{
printf("请录入第%d个整数:",i+1);
scanf("%d",ptr+i);
}
printf("你录入的整数是:");
for (i = 0; i < num; i++)
{
printf("%d ", ptr[i]);
}
free(ptr);
return 0;
}
评价:完美的代码,哈哈!
1. 坊间有传闻,说 malloc 最大可以申请 1GB 的内存空间……
但是,有的鱼油说可以成功申请到 2GB 的空间……
这样吧,咱自己写一个程序,计算 malloc 函数最大可以申请多少内存才能空间?
**这题不太理解**
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *block;
int i, count;
size_t maximum = 0;
size_t blocksize[] = {1024 * 1024, 1024, 1};
// 下面从大到小依次尝试
// 先尝试以1024 * 1024为扩大粒度去申请内存空间
// 当malloc返回NULL时,将扩大的粒度缩小为1024继续尝试
// 最终精确到1个字节的粒度扩大maximum的尺寸
for (i = 0; i < 3; i++)
{
for (count = 1; ;count++)
{
block = malloc(maximum + blocksize[i] * count);
if (block)
{
maximum += blocksize[i] * count;
free(block);
}
else
{
break;
}
}
}
printf("malloc在当前环境下申请到的最大空间是:%.2fGB\n", maximum * 1.0 / 1024 / 1024 / 1024);
return 0;
}