动态数组的遍历问题

update: 是另外的问题导致,直接访问 arr.length 正常

=========忽略以下=============
如下简略的伪代码,定义了一个动态数组 arrfn 函数用于遍历数组。
当 arr 中有元素的情况下,遍历一切正常。那么问题来了,在 arr 并没有被 push 任何元素的情况下,调用 arr.length 貌似就跪了。那么这种场景下怎么判断数组长度以避免执行异常呢?(我想到一个方法是另外定义一个 bool,用于标记数组中有没有元素,但这有点 stupid :sweat_smile:

contract C {
  address[] arr;

  function fn () public  {
    for (uint i=0; i<arr.length; i++)
      //do something
  }
}

@kaikai, 有没有好的方法?

什么版本的呢?
应该不会有这个问题的。

hi @kaikai, 刚试了一下确实没什么问题,是我之前 sol 生成 bin 时代码不完整导致。
但是我遇到另外一个问题,在做循环遍历时,莫名就跪了,收到的 TransactionReceipt 显示 Reverted 。有什么办法能知道到底哪里执行出错了吗?

如下是类似逻辑的简略代码,大致意思就是遍历所有子合约并改变一些赋值,(这份简易代码并不报错,可以执行,所以感觉非常 weird :joy:)我实际的代码中,如果把 for 循环中的 h.traverse 注释掉,执行成功,event 也能正常获取到,但是如果留着,就报错 Reverted,event 也获取不到。

是否 solidity 中对循环、递归的一些使用有什么要注意的地方?

contract HelloWorld {
    string name;
    address[] public children;

    event Log(address addr, string message);

    function traverse(string memory _name) public {
        name = _name;
        emit Log(address(this), 'name is changed');
        for(uint i=0; i< children.length; i++) {
            HelloWorld h = HelloWorld(children[i]);
            h.traverse(_name);
        }
    }

这里没看到递归的出口啊?

用递归会消耗栈空间,在 CITA 里,栈的大小为 1024 * U256 ,超过就会有 “out of stack” 错误。

@leeyr, 我理解其实并没有递归, for 循环中每次调用的 traverse 方法是子合约的。比如说 A B C 两个合约,A 的 children 列表是 B 和 C,B 和 C 的 children 都是空的没有元素,所以当 B、C 的 traverse 方法被调用时应该 for 循环是不会进去的。

会在 errormsg 中返回吗?我现在只能得到"Reverted."

你继续 deep in 就行了,问题可能不是出在循环,

这个是什么函数? 问题出在这个函数里,进去这个函数里面调试

sorry, 我看错了

一种可能的问题是,数组地址可能不对,调用函数报错

找到问题根源了,是自己太膨胀选择了 hard 模式学习 solidity:sweat_smile:
由于涉及到『合约中创建新合约』,代码里用了一个 factory 模型,实际上生成了两个合约的 bin,而我每次都忘记去更新 factory 合约的 bin,闹出这么多笑话 -.- …
anyway, thanks a lot @kaikai @leeyr

写个 talk 分享一下呗!!