内存逃逸

内存逃逸: 编译器将 函数局部变量 (即应该在栈内的数据) 分配到了堆上。 为什么发生?

  1. 因为外部引用,编译器帮忙自动纠错。
  2. 闭包
  3. 变量大小不确定(如slice), 编译器更倾向放在堆上
  4. 类型不确定 为什么要避免逃逸?
  5. 大量逃逸影响程序性能(堆被大幅度占用)

内存分配

一些编程语言如c,如果需要节省内存还需要自己手动管理struct中的成员变量顺序,以确保内存对齐。例如:

typedef struct {
    char a; // 1 byte
    uint32_t b; // 4 bytes
} Test; // 8 bytes
 
typedef struct {
    uint32_t b; // 4 bytes
    char a; // 1 byte
} Test2; // 8 bytes

在这里,由于char只占1个字节,而uint32_t占4个byte,为了内存对齐,编译器会在char后面填充3个byte,使得Test的大小为8个byte。

如果我们将uint32_t放在前面(即是Test2),那么Test2的大小就只有5个byte了。当然,实际上最后Test2的大小为8个byte,因为struct的内存大小必须是其最大成员大小的整数倍。也就是说在这里要4的倍数,那么可能就要迷惑了,那讲这个干嘛?

其实是因为如果你想我一样是个想到哪里写到哪里的人,那么最后可能会变成这样:

typedef struct {
    char a; // 1 byte
    uint32_t b; // 4 bytes
    char c; // 1 byte
    uint32_t d; // 4 bytes
} Test; // 16 bytes
 
typedef struct {
    uint32_t b; // 4 bytes
    uint32_t d; // 4 bytes
    char a; // 1 byte
    char c; // 1 byte
} Test2; // 12 bytes

或者可能再多一点点

typedef struct {
    char a; // 1 byte
    double b; // 8 bytes
    char c; // 1 byte
    uint32_t d; // 4 bytes
} Test; // 24 bytes
 
typedef struct {
    double b; // 8 bytes
    uint32_t d; // 4 bytes
    char a; // 1 byte
    char c; // 1 byte
} Test2; // 16 bytes