Closed chexiongsheng closed 4 months ago
其中一种修复办法:分配block时,多分配一个sizeof(internal::Address),浪费一点空间(每个block浪费1/1022),避免block间粘在一起。
补充下比较容易触发的场景:大量的HandleScope创建和销毁。比如JSON.parse解析超大json字符串。
如果C++规范没说不允许两块new的内存粘连,那这是v8的bug,否则这是ue的bug。
这个情况下很容易直接触发v8::abort()...用 -ansimalloc
可以绕开
如果C++规范没说不允许两块new的内存粘连,那这是v8的bug,否则这是ue的bug。
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf 256页: 7.22.3 Memory management functions Each such allocation shall yield a pointer to an object disjoint from any other object.
看起来是后者
把if语句中的 block_start <= prev_limit 改成 block_start < prev_limit 应该也能修复这个问题
我给V8官方提了一个修复: https://issues.chromium.org/issues/352446088
以v9.4.146.24为例,其handlescope的block释放代码如下:
其判断是否要结束循环的条件是(prev_limit)地址是否在[block_start, block_limit]范围,但如果两个block刚好分配时粘在一起(一块的尾地址等于另外一块的首地址),就有可能提前满足条件(prev_limit等于block_start),导致漏释放了block,进而导致数据上的错乱,最终在gc时崩溃。
v8一直没发现可能是因为一般内存分配器都会在返回地址前留个header,不会出现两块内存粘一起的情况。而ue重载了new,它的内存分配会有这种情况。