go icon indicating copy to clipboard operation
go copied to clipboard

panic sometimes....

Open h-hy opened this issue 7 years ago • 8 comments

panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x57b364]

goroutine 22 [running]: github.com/json-iterator/go.(*Stream).WriteStringWithHTMLEscaped(0xc4202fec60, 0x0, 0x36) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_stream_string.go:235 +0x94 github.com/json-iterator/go.(*htmlEscapedStringEncoder).Encode(0x16d4000, 0xc4210e4ea8, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_config.go:182 +0x41 github.com/json-iterator/go.(*structFieldEncoder).Encode(0xc4203049c0, 0xc4210e4d20, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect_object.go:118 +0x5c github.com/json-iterator/go.(*structEncoder).Encode(0xc420304fc0, 0xc4210e4d20, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect_object.go:155 +0xd5 github.com/json-iterator/go.(*OptionalEncoder).Encode(0xc420794a20, 0xc420774480, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect.go:124 +0x4f github.com/json-iterator/go.(*structFieldEncoder).Encode(0xc420782b40, 0xc420774480, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect_object.go:118 +0x5c github.com/json-iterator/go.(*structEncoder).Encode(0xc420782c20, 0xc420774480, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect_object.go:155 +0xd5 github.com/json-iterator/go.(*structEncoder).EncodeInterface(0xc420782c20, 0xd6eaa0, 0xc420774480, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect_object.go:175 +0x146 github.com/json-iterator/go.(*Stream).WriteVal(0xc4202fec60, 0xd6eaa0, 0xc420774480) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect.go:252 +0xe4 github.com/json-iterator/go.(*emptyInterfaceCodec).Encode(0x16d4000, 0xc42021c538, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect_native.go:369 +0x41 github.com/json-iterator/go.(*structFieldEncoder).Encode(0xc42032d560, 0xc42021c500, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect_object.go:118 +0x5c github.com/json-iterator/go.(*structEncoder).Encode(0xc42032d6a0, 0xc42021c500, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect_object.go:155 +0xd5 github.com/json-iterator/go.(*OptionalEncoder).Encode(0xc420011520, 0xc4201f1838, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect.go:124 +0x4f github.com/json-iterator/go.WriteToStream(0xccfd00, 0xc42021c500, 0xc4202fec60, 0x1671220, 0xc420011520) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect.go:47 +0xd2 github.com/json-iterator/go.(*OptionalEncoder).EncodeInterface(0xc420011520, 0xccfd00, 0xc42021c500, 0xc4202fec60) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect.go:129 +0x55 github.com/json-iterator/go.(*Stream).WriteVal(0xc4202fec60, 0xccfd00, 0xc42021c500) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_reflect.go:252 +0xe4 github.com/json-iterator/go.(*frozenConfig).Marshal(0xc420096280, 0xccfd00, 0xc42021c500, 0x0, 0x0, 0x0, 0x0, 0x0) /home/gitlab-runner/sy_go/src/github.com/json-iterator/go/feature_config.go:262 +0xd6 public/syLog.init.1.func1(0xc42006c480) /home/gitlab-runner/sy_go/src/public/syLog/log.go:69 +0xba created by public/syLog.init.1 /home/gitlab-runner/sy_go/src/public/syLog/log.go:63 +0x6d

h-hy avatar Aug 09 '18 12:08 h-hy

@h-hy would u show your code?

zhwentao avatar Aug 19 '18 06:08 zhwentao

同问, 非常偶然能出现这个问题,线上服务器,一天遇到2~3次

lixianmin avatar Dec 18 '18 04:12 lixianmin

必现,代码如图: image 多协程必现,单线程无误

piaohao avatar Jan 17 '19 08:01 piaohao

问题已解决,for循环变量的问题,多协程的情况下,由于闭包函数的原因,每次调用的基本都是最终的for循环变量,json在序列化的时候,并发引用同一个变量,导致内存指针错误,解决方案如下:

pool := workerpool.New(8)
expireTime := (7 * 24 * time.Hour).Seconds()
for key, shows := range self.showByCinemaDateMap {
	finalKey := key    //暂存临时变量
	finalShows := shows     //暂存临时变量
	pool.Submit(func() {
		if finalShows == nil {
			return
		}
		bytes, err := json.Marshal(finalShows)
		if err != nil {
			return
		}
		conn := configure.FilmShowRedis.Get()
		defer conn.Close()
		conn.Do("set", "filmShowByDate/"+finalKey, string(bytes))
		conn.Do("expire", "filmShowByDate/"+finalKey, expireTime)
	})
}
pool.StopWait()

piaohao avatar Jan 22 '19 03:01 piaohao

同问, 非常偶然能出现这个问题,线上服务器,一天遇到2~3次

同样问题,请问解决了咩

wushuangxiaoyu avatar Jul 25 '20 16:07 wushuangxiaoyu

能否提供复现问题的demo或者输入的json串协助进行问题定位和分析?

AllenX2018 avatar Jul 27 '20 11:07 AllenX2018

问题已解决,for循环变量的问题,多协程的情况下,由于闭包函数的原因,每次调用的基本都是最终的for循环变量,json在序列化的时候,并发引用同一个变量,导致内存指针错误,解决方案如下:

pool := workerpool.New(8)
expireTime := (7 * 24 * time.Hour).Seconds()
for key, shows := range self.showByCinemaDateMap {
	finalKey := key    //暂存临时变量
	finalShows := shows     //暂存临时变量
	pool.Submit(func() {
		if finalShows == nil {
			return
		}
		bytes, err := json.Marshal(finalShows)
		if err != nil {
			return
		}
		conn := configure.FilmShowRedis.Get()
		defer conn.Close()
		conn.Do("set", "filmShowByDate/"+finalKey, string(bytes))
		conn.Do("expire", "filmShowByDate/"+finalKey, expireTime)
	})
}
pool.StopWait()

why ref the same obj when json.Marshal(objs) would panic? we known that json.Marshal is goroutine safe.

beijingzhangwei avatar Dec 07 '21 03:12 beijingzhangwei

It can reproduce use the following code: `import ( jsoniter "github.com/json-iterator/go" "sync" "time" )

type XMD struct { Fields []string thrift:"fields,1" json:"fields,omitempty" }

func main(){ p := new(XMD) p.Fields = make([]string,0) //lock := sync.Mutex{}

wg:= sync.WaitGroup{}
wg.Add(1)
for j := 0; j < 10000; j++{
	p.Fields = make([]string,0)
	go func() {
		wg.Wait()
		for i:=0; i<100; i++{
			//lock.Lock()
			p.Fields = append(p.Fields, "7153211")
			//lock.Unlock()  // not ok
			jsoniter.MarshalToString(p)
			//lock.Unlock()    // ok
		}
	}()
}
wg.Done()
time.Sleep(100*time.Second)

} `

The core problem is incorrect use share object.

beijingzhangwei avatar Dec 08 '21 11:12 beijingzhangwei