slowmna

Results 5 comments of slowmna

> 应该是v8的认为后续代码用不上StructA了,于是释放了。 你试试在循环之后加一行代码访问下StructA。 是的,我们工程里最后加了一行打印StructA的Num后就不会出现此问题了,这算不算是v8的BUG?

> > > 应该是v8的认为后续代码用不上StructA了,于是释放了。 你试试在循环之后加一行代码访问下StructA。 > > > > > > 是的,我们工程里最后加了一行打印StructA的Num后就不会出现此问题了,这算不算是v8的BUG? > > 其实按v8运行的实例和时长来说,和操作性核心模块是一个级别的。有问题动不动怀疑是v8的bug有点盲目自信了。 我懂你意思了,也就是for of因为是迭代的目标是StructA.MyTestB, 而不是StructA本身, 而JavaScript本身是可以单独引用MyTestB而释放StructA的,这种情况下激进的GC策略也不会导致BUG。但仍然是一个危险的优化,这个GC的行为越过了通常意义上理解的生命周期, 我特地搜索了ECMAScript6规范,let 变量的作用域是块级作用域,v8错误的估计了从JavaScript的代码上没有访问,于是在块结束前就提前GC了。照这么说来。 WITH_OUTER_LINK这个宏就不是可选项,而是必选项。这不是我们的疏忽,是v8的激进策略和宿主语言的不搭配导致的。 不可能,也不应该有人预先假设块级作用域在退出{}之前就释放。如果v8没有提供任何规避此问题的手段的话,我只能说这玩意就是给纯JavaScript环境用的吧,和宿主语言的跨语言调用现在这样子能用? 按照我的理解来说,如果不加这个宏,下面的语句也可能崩溃: ![image](https://github.com/Tencent/puerts/assets/38640830/848724b8-e0da-4d98-9a61-abcb001c2eb8) 因为从获取到StructA之后就没有直接对StructA的访问了,后续用的都是MyTestB,按照这个情况来看,基本上用到UStruct 的地方,几乎都可以明明白白非常正当的崩溃

> 我觉得你是把c++的scope的一些对象声明周期管理给拿到其它语言了。 scope只有变量可见性是各语言通用的。es规范也是指这个。 scope结束释放对象是c++这种不带gc语言的特殊设定。 对于带gc的语言,gc何时释放对象显然和scope没关,即不保证scope结束对象必须gc完成,也不保证scope前不得释放对象,或者你在es规范找下这方面的定义?c++的scope结束释放对象是在c++标准里的。 行吧,一般人都容易想到 GC生命周期 >= 可见性,没见过 GC生命周期 < 可见性 的, 那对于这样的问题怎么办?只有把WITH_OUTER_LINK改成默认打开了吧 ![image](https://github.com/Tencent/puerts/assets/38640830/a83f178a-68d0-47ae-9c1d-7fbf02e8ff59)

> 你这种情况反而比较少见,所以WITH_OUTER_LINK也不是专门解决这种问题。 WITH_OUTER_LINK解决的是这些更容易犯的错误: foo(StrunctA.MyTestB);//然后foo把参数存起来用 > > let test = StrunctA.MyTestB botton.onClick = () = { test.xxx; } > > 有个团队(有比较多的外包)如上错误比较多,所以我加了WITH_OUTER_LINK,但我不知道是不是普遍现象。 你说的这个问题我们考虑到了,所以我们才觉得只要我持有最外层的Struct的引用,内层的的值就不会释放,现在看起来并不能,最外层的值在v8看起来没有再用了就可能会释放。我猜其他团队也许是恰好最外层还在用,而且本身这个复现的几率就很小。 但对于我举例的三行代码,除了这个宏和v8不要在可见性内GC两种手段之外,没有什么很好的解决方案。我打算打开这个宏算了。

你这么说也没错,我是没想到这个脚本语言都能优化到这样,而且for of这里不算是引用StructA也很隐蔽(相当于有个this = StructA.MyTestB ?所以第二次循环就不会在用到StructA了) 要是说C++ 定义了一个变量,没有显式使用,然后通过栈顶指针推算这个变量的地址去访问。结果这个变量其实被优化没了导致访问出错很多人还是能想到的