Solidity中修改bytes内存元素导致日志不输出问题求助
Solidity中修改string转bytes时日志消失的问题解决
我之前踩过完全一样的坑!这问题乍一看摸不着头脑,但其实是Solidity内存模型的一个容易忽略的细节导致的,让我给你拆解清楚:
问题根源:string转bytes得到的是只读视图
当你执行bytes memory aa = bytes(sl);时,Solidity并没有给你创建一个全新的可修改bytes数组——它只是生成了一个指向原string内存区域的只读视图。
在Solidity里,memory类型的string本身是不可变的(你没法直接修改string的单个字符),对应的bytes视图自然也不允许修改。当你尝试执行aa[0] = 2;时,本质是在写入一块被标记为只读的内存,这会直接触发EVM的内存访问违规,导致整个交易回滚。而日志是在交易成功执行后才会被记录的,所以你看不到log("123")的原因,是交易还没走完流程就失败回滚了,所有操作记录都被清除了。
解决办法:创建可修改的bytes副本
要修改从string转来的bytes内容,你得先把原string的内容复制到一个全新的、可修改的bytes数组里,有两种简单的方式:
方式1:手动循环复制
function get() public{ string memory sl = "asddsa"; bytes memory originalBytes = bytes(sl); // 创建一个长度相同的新bytes数组 bytes memory aa = new bytes(originalBytes.length); // 复制原内容 for(uint i = 0; i < originalBytes.length; i++){ aa[i] = originalBytes[i]; } log("123"); aa[0] = 2; // 现在修改就不会有问题了 }
方式2:用abi.encodePacked快速生成副本
abi.encodePacked(sl)会直接生成一个包含string内容的新bytes memory数组,这个数组是可修改的,代码更简洁:
function get() public{ string memory sl = "asddsa"; bytes memory aa = abi.encodePacked(sl); log("123"); aa[0] = 2; // 正常执行,日志也能看到 }
关于Library中的情况
如果你把这段逻辑放到Library里,问题的本质还是一样的:只要你直接修改从string转来的只读bytes视图,依然会触发内存错误导致交易回滚。解决思路也完全相同——先创建可修改的副本,再进行修改操作。
敲黑板划重点
- 永远记住:
bytes(string memory)返回的是只读视图,不是可修改数组; - 交易回滚会清除所有日志记录,所以看不到日志不一定是log语句的问题,很可能是之前的代码导致交易失败了;
- 要修改string对应的bytes内容,必须先创建独立的可修改副本。
内容的提问来源于stack exchange,提问作者Pittie
相关产品推荐
相关产品推荐

