3

如何在Golang中制造stack overflow 故障

 3 years ago
source link: http://vearne.cc/archives/1464
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何在Golang中制造stack overflow 故障

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://vearne.cc

大家都知道golang的栈的动态增长的,并且是放在堆上的,理论上可以相当的大,那么怎么才能制造一个stack overflow 故障呢?
其实只要人为的加入循环引用就能做到

package main

import (
    //"github.com/json-iterator/go"
    "encoding/json"
)

type A struct {
    ElementB *B
}

type B struct {
    ElementA *A
}

func main(){
    a := A{}
    b := B{}

    a.ElementB = &b
    b.ElementA = &a
    //var json = jsoniter.ConfigCompatibleWithStandardLibrary
    json.Marshal(a)
}

栈溢出,程序奔溃,并输出

╰─$ go run test_stackoverflow2.go                                   
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x10e2e65, 0xe)
    /usr/local/Cellar/go/1.11.2/libexec/src/runtime/panic.go:608 +0x72
runtime.newstack()
    /usr/local/Cellar/go/1.11.2/libexec/src/runtime/stack.go:1008 +0x729
runtime.morestack()
    /usr/local/Cellar/go/1.11.2/libexec/src/runtime/asm_amd64.s:429 +0x8f

goroutine 1 [running]:
encoding/json.(*structEncoder).encode(0xc0000642d0, 0xc00007e000, 0x10c8d40, 0xc00000c030, 0x199, 0x100)
  • 看来默认栈的最大大小也就1GB。
  • 这个例子其实源于真实的线上故障,经过测试无论是标准的Json库,或是jsoniter都无法避免此问题。
  • 另外如果Golang编译器,或者Marshal函数能够对递归的深度做出判断,超过一定深度就报错,在栈溢出前,抛出err,避免栈溢出,程序崩溃

已经给json-iterator/go 提了issue,并且提了pull request。
有需要也可以直接使用我个改进库vearne/json-iterator-go
默认递归的最大层级限制是1000


如果我的文章对你有帮助,你可以给我打赏以促使我拿出更多的时间和精力来分享我的经验和思考总结。

微信支付码

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK