英文:
Go json Marshaller panics with "call of reflect.Value.Int on zero Value"
问题
我正在尝试在一个具有多级嵌套的复杂结构中解组一些数据(因此,不在此处复制结构)。然而,当代码上线后,我们开始在偶尔的情况下(很难量化,但可能是1000个案例中的1个)遇到以下恐慌。
以下是问题的堆栈跟踪:
panic: reflect: call of reflect.Value.Int on zero Value [recovered]
panic: reflect: call of reflect.Value.Int on zero Value
goroutine 568428 [running]:
encoding/json.(*encodeState).marshal.func1(0xc0081d5c70)
/usr/local/go/src/encoding/json/encode.go:305 +0x9a
panic(0x13968c0, 0xc005c2f540)
/usr/local/go/src/runtime/panic.go:679 +0x1b2
reflect.Value.Int(...)
/usr/local/go/src/reflect/value.go:986
encoding/json.intEncoder(0xc0074b5dc0, 0x0, 0x0, 0x0, 0xc0038b0100)
/usr/local/go/src/encoding/json/encode.go:522 +0x1d4
encoding/json.mapEncoder.encode(0x1608760, 0xc0074b5dc0, 0x1385c20, 0xc00119f5e0, 0x195, 0x100)
/usr/local/go/src/encoding/json/encode.go:706 +0x351
encoding/json.structEncoder.encode(0xc0002ce600, 0x19, 0x21, 0xc00027ede0, 0xc0074b5dc0, 0x156c820, 0xc00119f510, 0x199, 0x520100)
/usr/local/go/src/encoding/json/encode.go:664 +0x306
encoding/json.ptrEncoder.encode(0xc00027ee10, 0xc0074b5dc0, 0x1397e80, 0xc00119f510, 0x16, 0x1390100)
/usr/local/go/src/encoding/json/encode.go:810 +0xb1
encoding/json.(*encodeState).reflectValue(0xc0074b5dc0, 0x1397e80, 0xc00119f510, 0x16, 0x100)
/usr/local/go/src/encoding/json/encode.go:337 +0x82
encoding/json.(*encodeState).marshal(0xc0074b5dc0, 0x1397e80, 0xc00119f510, 0xc003da0100, 0x0, 0x0)
/usr/local/go/src/encoding/json/encode.go:309 +0x10b
encoding/json.Marshal(0x1397e80, 0xc00119f510, 0x40be53, 0x13c4160, 0x1397e80, 0x1, 0x7fa9d5d348b0)
/usr/local/go/src/encoding/json/encode.go:161 +0x52
reingames.com/rm/user.(*userCore).MarshalBinary(0xc00119f510, 0x1397e80, 0xc00119f510, 0x7fa9d5d348b0, 0xc00119f510, 0x1)
/home/shivam/goprojects/rmgs/go/user/profile.go:180 +0x37
我不知道从哪里开始调试这个问题。有人遇到过类似的情况吗?简短的问题:在更新指针时进行编组(marshalling)可能会导致这种恐慌吗?
谢谢
英文:
I am trying to unmarshal some data in a complex struct with multi-level nesting (thus, not copying the struct here). However, when the code went live, we started getting the following panic in rare occasions (difficult to quantify but perhaps 1 in 1000 cases).
Below is the stack trace of the issue:
panic: reflect: call of reflect.Value.Int on zero Value [recovered]
panic: reflect: call of reflect.Value.Int on zero Value
goroutine 568428 [running]:
encoding/json.(*encodeState).marshal.func1(0xc0081d5c70)
/usr/local/go/src/encoding/json/encode.go:305 +0x9a
panic(0x13968c0, 0xc005c2f540)
/usr/local/go/src/runtime/panic.go:679 +0x1b2
reflect.Value.Int(...)
/usr/local/go/src/reflect/value.go:986
encoding/json.intEncoder(0xc0074b5dc0, 0x0, 0x0, 0x0, 0xc0038b0100)
/usr/local/go/src/encoding/json/encode.go:522 +0x1d4
encoding/json.mapEncoder.encode(0x1608760, 0xc0074b5dc0, 0x1385c20, 0xc00119f5e0, 0x195, 0x100)
/usr/local/go/src/encoding/json/encode.go:706 +0x351
encoding/json.structEncoder.encode(0xc0002ce600, 0x19, 0x21, 0xc00027ede0, 0xc0074b5dc0, 0x156c820, 0xc00119f510, 0x199, 0x520100)
/usr/local/go/src/encoding/json/encode.go:664 +0x306
encoding/json.ptrEncoder.encode(0xc00027ee10, 0xc0074b5dc0, 0x1397e80, 0xc00119f510, 0x16, 0x1390100)
/usr/local/go/src/encoding/json/encode.go:810 +0xb1
encoding/json.(*encodeState).reflectValue(0xc0074b5dc0, 0x1397e80, 0xc00119f510, 0x16, 0x100)
/usr/local/go/src/encoding/json/encode.go:337 +0x82
encoding/json.(*encodeState).marshal(0xc0074b5dc0, 0x1397e80, 0xc00119f510, 0xc003da0100, 0x0, 0x0)
/usr/local/go/src/encoding/json/encode.go:309 +0x10b
encoding/json.Marshal(0x1397e80, 0xc00119f510, 0x40be53, 0x13c4160, 0x1397e80, 0x1, 0x7fa9d5d348b0)
/usr/local/go/src/encoding/json/encode.go:161 +0x52
reingames.com/rm/user.(*userCore).MarshalBinary(0xc00119f510, 0x1397e80, 0xc00119f510, 0x7fa9d5d348b0, 0xc00119f510, 0x1)
/home/shivam/goprojects/rmgs/go/user/profile.go:180 +0x37
I have no clue where to start debugging this. Has anyone experienced something similar? Quick question - could a race condition (marshalling a pointer while it is being updated) cause this panic?
Thanks
答案1
得分: 1
是的,竞争条件可能导致几乎任何问题,包括这个问题。如果你有任何测试,可以使用go test -race
来运行它们。如果没有测试,或者运行测试没有发现问题,你可以考虑使用go build -race
来构建一个金丝雀版本,但是请参考竞争条件检测器文档中关于性能和内存使用方面的注意事项。你也可以自己检查代码是否存在竞争条件。
英文:
Yes, a race could cause almost anything, including this. If you have any tests to speak of, run them with
go test -race
. If not, or if that doesn't turn anything up, you might consider canarying a build with
go build -race
, but see the race detector documentation for caveats about performance and memory usage in that case. You may just want to inspect the code yourself for races.
答案2
得分: 1
一种开始调试的方法是:使用recover()
指令捕获panic,并记录有关错误上下文的信息。
这种方法不能捕获正在进行的竞态条件,但它肯定能帮助你更好地理解错误(它是否总是发生在相同的元素上?该元素是否仍处于有效状态等等...)。
英文:
One way to start debugging is : catch the panic with a recover()
instruction, and log information about the context of the error.
This wouldn't catch a race condition "in the act", but it would certainly help you understand more things about your error (does it occur always on the same elements ? is the element still in a valid state ? etc ...)
答案3
得分: 0
最近,我们也遇到了这个问题,你可以检查一下代码中是否使用了协程,并且是否有正确的切片操作。切片依赖于数组的实现。当底层数组有足够的容量时,追加操作不是只读操作,元素会直接添加到数组的空闲位置。因此,当多个协程对全局切片进行追加操作时,它们会对同一份底层数据进行操作,导致读写冲突。这会导致Go的JSON编组器出现异常。
英文:
Recently, we also have this problem, you can check whether it is a coroutine in the code,Is there a right slice operate。Slice relies on array implementation. When the underlying array has sufficient capacity, the append operation is not a read-only operation, and elements are directly added to the free position of the array. Therefore, when a multi-coroutine performs an append operation on a global slice, it will operate on the same underlying data, causing read-write conflicts. Causes the exception of Go json Marshaller.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论