内存中的布局

Solidity 保留了四个 32 字节的槽,具体的字节范围(包括端点)如下:

  • 0x00 - 0x3f (64 字节):哈希方法的临时空间

  • 0x40 - 0x5f (32 字节):当前分配的内存大小(即空闲内存指针)

  • 0x60 - 0x7f (32 字节):零槽

临时空间可以在语句之间使用(即在内联汇编中)。 零槽用作动态内存数组的初始值,永远不应被写入(空闲内存指针最初指向 0x80)。

Solidity 始终将新对象放置在空闲内存指针处,并且内存永远不会被释放(将来可能会改变)。

Solidity 中内存数组的元素始终占用 32 字节的倍数(即使对于 bytes1[] 也是如此,但不适用与 bytesstring)。 多维内存数组是指向内存数组的指针。动态数组的长度存储在数组的第一个槽中,后面是数组元素。

警告

Solidity 中有一些操作需要一个大于 64 字节的临时内存区域,因此无法放入临时空间。 它们将被放置在空闲内存指向的位置,但由于其短暂的生命周期,指针不会更新。 内存可能会被清零,也可能不会。 因此,不应期望空闲内存指向已清零的内存。

虽然使用 msize 来获得一个确定已清零的内存区域似乎是个好主意,但在不更新空闲内存指针的情况下使用这样的非临时性地指针可能会产生意想不到的结果。

与存储中的布局的区别

如上所述,内存中的布局与 storage 中的布局不同。下面是一些示例。

数组差异示例

以下数组在存储中占用 32 字节(1 个槽),但在内存中占用 128 字节(4 个元素,每个 32 字节的)。

uint8[4] a;

结构体布局差异示例

以下结构在存储中占用 96 字节(3 个 32 字节的槽),但在内存中占用 128 字节(4 个元素,每个 32 字节)。

struct S {
    uint a;
    uint b;
    uint8 c;
    uint8 d;
}