Memory Management in C++ (Abandoned)

1. 动态内存分配

在 ICS 中,我们学习了可执行目标文件视图的ELF可执行文件。我们了解了堆内存、栈内存、bss段、data段、text段等等的作用。程序运行时总是需要内存的,怎么办呢?我们要使用动态内存分配器,如malloc来让程序载入内存运行时能获取内存。

动态内存分配器管理进程虚拟内存的堆内存,在32位机器上,堆内存往往能占到进程虚拟内存的1/2甚至3/4,即2GB-3GB的空间。我们将虚拟内存划分成一个个“块(Blocks)",这也是内存分配器分配内存的最小单位。通常来说,一个块的大小是512KB或4096KB,和磁盘的最小存储单位相同。

1.1 分配器的种类

1.1.1 显式分配器

如C语言中的mallocfree,需要手动人工释放已经分配的内存。

1.1.1 隐式分配器

如Java(Garbage Collection)。应用申请内存,释放自动完成。

2. mallocfreenewdelete的区别

2.1 The malloc Package

2.1.1 malloc
#include <stdlib.h>

void *malloc(size_t size)

当申请成功,返回一个指向申请内存块的的指针,申请的内存以字节为单位。如果 size == 0返回NULLerrno也就是申请失败。

在程序启动的时候,glibc库中的malloc会为用户申请一小段堆内存作为内存池。

2.1.2 free

参数: ptr: 指向要释放的内存块的指针。如果 ptrNULL,则 free 不执行任何操作。
注意事项:

  • 释放内存后,指针 ptr 变为悬空指针(dangling pointer),应将其设置为 NULL 以避免悬空指针错误。
  • 释放未分配或已释放的内存会导致未定义行为。
    示例代码:
#include <stdlib.h>
#include <stdio.h>

int main() {
    int *p = (int *)malloc(10 * sizeof(int));
    if (p == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    // 使用分配的内存
    for (int i = 0; i < 10; i++) {
        p[i] = i;
    }

    // 释放内存
    free(p);
    p = NULL; // 避免悬空指针

    return 0;
}

这个示例中,malloc 分配了一个包含 10 个 int 类型元素的内存块,使用完后通过 free 释放内存,并将指针 p 设置为 NULL

free怎么知道释放哪些内存空间?这是因为在内存分配时,分配器会在分配的内存块中存储一些额外的信息。这些信息通常包括内存块的大小和其他管理数据。

2.2 new和delete

new和malloc的区别就是new在申请时会调用构造函数,如:

int parr = new int(10);//调用构造函数
int parr = new int;
#include <iostream>
#include <functional>

int (*FuncPtr)(int, int) funcp1;

typedef int (*FuncPtrII)(int, int);
FuntPointerII funcp2;

std::function<int(int,int)> funcp3;