-
Notifications
You must be signed in to change notification settings - Fork 18k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
reflect: DeepEqual panics when encountering a pointer cycle #33907
Comments
I think you mean it panics when it encounters a cycle. A nested map would be something like I agree DeepEqual shouldn't reach a stack overflow in this case. If you want to work on a fix, that's welcome. |
reflect.DeepEqual
panics with stack overflow when comparing two nested maps
There is no well-defined constructive equality over the infinite objects like in the given example. Good luck with "working on a fix" for this. |
@av86743 please be nice; there's no need to tell new Go contributors "good luck with this". This is documented, though:
So I think it's reasonable to follow this rule and also make this case terminate. |
This comment has been minimized.
This comment has been minimized.
This is not true. |
@av86743 please only leave comments if you're going to provide useful input or constructive criticism. For example, why is this not true? If you think it isn't, file a new issue. It seems to me like the case reported here can be fixed, following the rule already documented, so there's no reason to continue insisting in this thread. Also, a second reminder about https://golang.org/conduct. |
This comment has been minimized.
This comment has been minimized.
I have a quick fix on this. The root cause is simple: --- deepequal.old 2019-08-28 20:48:58.000000000 +0800
+++ deepequal.go 2019-08-28 21:26:13.000000000 +0800
@@ -34,17 +34,19 @@
// We want to avoid putting more in the visited map than we need to.
// For any possible reference cycle that might be encountered,
// hard(t) needs to return true for at least one of the types in the cycle.
- hard := func(k Kind) bool {
+ hard := func(k Kind, v1, v2 Value) bool {
switch k {
- case Map, Slice, Ptr, Interface:
+ case Map, Slice, Ptr:
return true
+ case Interface:
+ return v1.CanSet() && v2.CanSet()
}
return false
}
- if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
- addr1 := unsafe.Pointer(v1.UnsafeAddr())
- addr2 := unsafe.Pointer(v2.UnsafeAddr())
+ if hard(v1.Kind(), v1, v2) {
+ addr1 := v1.ptr
+ addr2 := v2.ptr
if uintptr(addr1) > uintptr(addr2) {
// Canonicalize order to reduce number of entries in visited.
// Assumes non-moving garbage collector. |
@huandu Great! Please send a CL (see https://tip.golang.org/doc/contribute.html) and we can take it from there. |
Change https://golang.org/cl/191940 mentions this issue: |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
https://play.golang.org/p/YJE6T3aprvt
What did you expect to see?
No stack overflow.
reflect.DeepEqual
should returntrue
.What did you see instead?
reflect.DeepEqual
fails with stack overflow.The text was updated successfully, but these errors were encountered: