内存中的存储结构

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

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

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

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

临时空间可以在语句之间使用(即在内联汇编之中)。 0 值插槽则用来对动态内存数组进行初始化,且永远不会写入数据 (因而可用的初始内存指针为 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;
}