Solidity - “编译器错误:堆栈太深”

问题描述

想知道是否有人可以帮助我解决我在 solidity 合同中遇到的错误

我收到错误“堆栈太深”。我理解错误背后的含义,但我无法修复它。

此处发生错误(第 3 行):

function _getValues(uint256 tAmount) private view returns (uint256,uint256,uint256) {
        (uint256 tTransferAmount,uint256 tFee,uint256 tLiquidity,uint256 tMarketing,uint256 tBurn) = _getTValues(tAmount);
        (uint256 rAmount,uint256 rTransferAmount,uint256 rFee) = _getRValues(tAmount,tFee,tLiquidity,tMarketing,tBurn,_getRate());
        return (rAmount,rTransferAmount,rFee,tTransferAmount,tBurn);
    }

解决方法

正如文档中提到的:

EVM 不是寄存器机而是堆栈机,所以所有 计算在称为堆栈的区域上执行。它有一个 最大大小为 1024 个元素,包含 256 位字。

对栈的访问被限制在顶端,方法如下: 可以将最上面的 16 个元素之一复制到 将最上面的元素与下面 16 个元素之一堆叠或交换

所有其他操作取最上面的两个(或一个或多个,取决于 在操作上)元素从堆栈并将结果推送到 堆栈。

当然可以将堆栈元素移动到存储或内存中, 但不可能只访问更深层次的任意元素 无需先移除栈顶即可堆叠。

数字 16 和最后一部分很重要。

这基本上意味着 ETH 机器有“使用中的局部变量不超过 16 个”的限制。

另外,16 也不是一个严格的限制,它可以更小,这取决于你对变量的处理方式,而且这个限制是由于 EVM 只能达到特定的堆栈深度和局部变量存储在 Solidity 中的堆栈中。

我建议重构您的代码并将其拆分为两个函数,并从您的调用者处对每个数据块进行顺序查询,或者将变量缩小为结构体。

,

@MrFrenzoid 已经解释了这个错误的原因,所以我跳过那部分。

您可以通过将单体函数分解为多个细粒度的可重用函数来缓解此问题,或者您可以在函数内部使用 scopes 从堆栈中删除未使用的变量以腾出空间。