Solidity中的数据存储与EVM内存分配机制

—— 首先,为了更好地理解EVM(以太坊虚拟机)中的内存管理机制,我们还是先来看看Solidity中的基本数据类型。

        -值类型:

        包括整型(int/uint),地址型(address),布尔(Booleans),定长字节数组(fixed byte arrays),枚举类型(Enums)...在内的基本数据类型,在合约中都是以值的类型进行传递(赋值);

        -引用类型:

        而那些复杂类型,占用空间较大的。考虑到在拷贝到内存时成本比较大。所以考虑通过引用传递。比如,不定长字节数组(bytes),字符串(string),数组(Array),结构体(Struts)。


—— 存储位置:Solidity中的数据存储方式有如下3种

        -memory (内存,生命周期仅为整个方法执行期间,函数调用后回收,因为仅保存临时变量,故GAS开销很小)

        -storage (永久储存在区块链中,由于会永久保存合约状态变量,故GAS开销也最大)

        -栈 (存放部分局部值类型变量,几乎免费使用的内存,但有数量限制)

—— 在Solidity语言设计中,所有复杂数据类型都有一个额外的属性(location)来记录当前值的存储位置,而且大多时候该属性都是有默认值的,比如:

        -函数的参数和返回值默认是memory

        -局部复杂类型变量和状态变量默认是storage,而值类型的局部变量存在栈中

—— 值得注意的坑

        -在Solidity中创建结构和定长数组,如果指定存储在Storage中,EVM总是会开辟新的存储块并占用整个块空间,包括预留空间在内,故对应的内存永远不会被释放,存在区块链中

       -初始化后的数组,其第一个存储槽内存放的是该数组的length属性,也可以通过修改length属性来动态修改数组长度(memory中的变长数组除外),定长数组初始化后,所有下标都有默认值,如果删除了下标所对应的数据实例,该下标之后的所有数据并不会前移,所以会造成存储空间的浪费,所以不推荐使用数组进行频繁的写入和修改操作。

         -静态尺寸大小的变量,在32字节单位的存储槽空间中是紧凑排列的,不足32字节的多条数据会被连续存放同一个存储块中,如果新数据导致存储块空间溢出的话,就会被移动到下一个存储块中,例如连续声明3个变量uint128,uint256,uint128,这将占用3个存储槽,而如果是uint128,uint128,uint256顺序的话,就只会占用2个存储槽。

        -关于多维数组,声明一个多维数据,如一个由5个动态数组构成的定长数组,语法为 uint[][5] arr;而要访问下标为2的数据的下标为1的元素,访问语法为 arr[2][1],相比与其他很多语言,Solidity在这点非常反人类,即多维数组的声明与访问下标顺序,是反的!反的!的!


下一篇文章,我们来细数一下关于Storage与Memory相互转换的问题。


你可能感兴趣的:(Solidity中的数据存储与EVM内存分配机制)