Ethereum Solidity-Truffle:错误:处理事务时VM异常:操作码无效不是因为还原

Ethereum Solidity-Truffle:错误:处理事务时VM异常:操作码无效不是因为还原,ethereum,solidity,smartcontracts,opcode,truffle,Ethereum,Solidity,Smartcontracts,Opcode,Truffle,我正在开发一个智能合约,并通过在truffle上部署它来测试它。虽然它编译得很好,但当我调用train()函数时,会出现以下错误: 错误:处理事务时发生VM异常:操作码无效 在读了一点这方面的内容后,我了解到它通常是在发生恢复后引起的,所以我尝试注释了2个require函数,只是想看看它是否会有不同的行为,但事实并非如此 检查这个问题对我并没有帮助,或者我不知道它是怎么回事 这是train()函数,以及我在其中使用的映射和结构类型。我应该注意的是,在开发人员创建时,他们的钱包设置为300,因此我

我正在开发一个智能合约,并通过在truffle上部署它来测试它。虽然它编译得很好,但当我调用train()函数时,会出现以下错误:

错误:处理事务时发生VM异常:操作码无效

在读了一点这方面的内容后,我了解到它通常是在发生恢复后引起的,所以我尝试注释了2个require函数,只是想看看它是否会有不同的行为,但事实并非如此

检查这个问题对我并没有帮助,或者我不知道它是怎么回事

这是train()函数,以及我在其中使用的映射和结构类型。我应该注意的是,在开发人员创建时,他们的钱包设置为300,因此我看不出车主对列车功能的第一次调用如何恢复

结构开发人员{ 地址所有者; 字符串名; 字节32名称散列; bytes32[]技能; uint256[]技能水平; 银包; } 映射(bytes32=>Developer)公共开发者; 功能序列(字符串_名称,字节32 _技能)公共{ bytes32 h=keccak256(abi.encodePacked(_name)); require(developers_all[h].owner==msg.sender,“只有开发人员的所有者才能培训他们”); 要求(开发商所有[h]。钱包>=150,“资金不足”); uint256i=0; 做{ 如果(开发者所有[h].skills[i]====\u skill){ 开发者所有[h]。技能水平[i]++; }else if((i==(developers_all[h].skills.length-1))| |(developers_all[h].skills.length==0)){ 开发者所有[h].skills.push(\u skill); 开发者所有[h]。技能水平。推送(1); } i++; }而(i
感谢您的帮助。

这很可能是因为您正在尝试访问空数组的第一个条目。您使用的是do while循环,在检查
developers\u all[h].skills[i]
之前,您试图访问
developers\u all[h].skills.length==0
,因此在do while中的第一个if语句中数组可能为空

您可以将代码重写为以下内容,以确保永远不会访问未分配的阵列插槽

bool foundSkill=false;
for(uint i=0;i
请注意,在整个数组中循环并进行比较的成本非常高,如果数组太大,则可能无法进行比较。您可能需要考虑将结构更改为:

结构开发人员{ 地址所有者; 字符串名; 字节32名称散列; 映射(bytes32=>uint)技能水平; 银包; }
这样你就可以用

developers_all[h]。技能水平[skill]++;

但是你不能循环使用这些技能。

谢谢你,这与我最后所做的非常相似。我最初有一个带有映射的版本,但是因为后来我使用了一个getter函数,我需要能够返回所有技能,而我还没有找到一种方法来返回映射的所有元素。是的。事实证明这是真的。在我的代码中,我也遇到了这个错误,然后我创建了一个新函数来获取数组的大小,它的大小为零。关于如何在不使用额外函数的情况下获得数组大小的任何想法,看起来都是不可能的。看见