计算机基础-内存分配
文章目录
- 基本概念
- 内存分配的基本类型
- 静态分配(Static Allocation)
- 动态分配(Dynamic Allocation)
- 内存段
- 内存管理中的常见问题
- 内存泄漏
- 内存碎片
- 缓冲区溢出
- 问题练习
- 问题一
- 问题二
- 问题三
基本概念
计算机内存是由物理内存(RAM)和虚拟内存两部分组成的。在程序运行时,操作系统需要将程序所需的数据和指令加载到内存中。内存分配指的是操作系统如何将这些内存区域分配给运行中的程序或其子部分(如线程、进程等)。
内存分配的主要任务是确保程序能够高效、安全地访问所需的内存。分配过多的内存会浪费资源,而分配不足的内存会导致程序崩溃或运行缓慢。
内存分配的基本类型
静态分配(Static Allocation)
静态分配是在编译时确定的内存分配方式。程序中每个变量和数据结构的大小和位置在编译时就已固定,因此在程序运行时无需重新分配。这种方式的优点是简单且快速,但缺点是灵活性差,一旦程序编译完成,内存分配就不可再调整。
例子:全局变量和常量。
动态分配(Dynamic Allocation)
动态分配是在程序运行时进行的内存分配。它允许程序根据需要在运行时分配和释放内存,提供了更大的灵活性。动态内存分配通常通过内存管理函数来实现,如 malloc()、free()(在 C/C++ 中)等。
动态分配的常见问题包括内存泄漏(未释放的内存)、内存碎片(空闲内存被分割成多个小块,导致难以利用)。
内存段
内存段(Memory Segments)是操作系统和编译器用来管理程序运行时的内存区域。每个内存段有特定的用途,并且它们通常被划分为不同的部分,以便合理地管理程序的数据、代码和执行过程。
内存区域 | 描述 |
---|---|
堆(heap) | 动态内存分配区域,使用 new 或 malloc 分配的内存来自这里 |
栈(stack) | 用于函数调用、局部变量和返回地址等数据 |
代码段(Text) | 存储程序的可执行指令,通常是只读的 |
数据段 | 已初始化数据段:存储已初始化的全局变量和静态变量。 未初始化数据段(BSS):存储未初始化的全局变量和静态变量,程序加载时会自动清零。 |
文字常量区 | 存储程序中的常量数据,如字符串常量,通常为只读 |
只读数据段(RODATA) | 存储全局/静态const常量和字符串字面量 |
内存管理中的常见问题
内存泄漏
内存泄漏发生在程序分配了内存后,没有及时释放,导致这些内存块一直被占用,最终可能耗尽系统内存。为了避免内存泄漏,程序员需要确保每次分配的内存都被正确释放。
内存碎片
内存碎片是指内存中的空闲区域被分割成多个小块,导致无法有效利用这些内存。内存碎片可能会导致系统性能下降,特别是在频繁分配和释放内存的程序中。
缓冲区溢出
缓冲区溢出是指程序向内存中写入数据时,超出了预定的内存空间,从而破坏了其他内存数据。缓冲区溢出是常见的安全漏洞,攻击者可以利用它来执行恶意代码。
问题练习
问题一
int *p = new int[5];
delete[] ;
delete[] 为什么能知道删除几个
答:编译器在内存分配时会在 p 指向的内存块前面存储有关数组大小的元数据。当你调用 delete[] 时,编译器会根据这个元数据来删除整个数组。
问题二
#define是否占用内存
答: 不占用内存,在编译的时候,编译器会对对应的值进行替换
问题三
char *a = ”123";
这行指令是如何占用内存的?
答:
char *a = ”123"; 使用了两片内存;
只读数据段:存储 “123”(4 字节)。
栈:存储指针 a 本身(4 字节或者 8 字节,取决于平台)。