Checking for slice overlap

555 views
Skip to first unread message

Maxim Khitrov

unread,
Oct 15, 2012, 10:58:15 AM10/15/12
to golang-nuts
Hello,

Is there a safe(r) way of checking whether two slices point to the
same underlying array than going through unsafe.Pointer and casting
the result to reflect.SliceHeader?

I have a solution that works, but I'm not sure how to interpret the
SliceHeader warning: "It cannot be used safely or portably." Is that
in reference to different architectures, Go compilers, Go versions, or
all of the above?

A demo of my solution is here, but you have to run it locally due to
the unsafe import:

http://play.golang.org/p/gwJtKK__gG

One function tells you if two byte slices share the same array.
Another returns the overlapping region, if there is one.

- Max

Peter S

unread,
Oct 15, 2012, 11:12:37 AM10/15/12
to Maxim Khitrov, golang-nuts
From http://golang.org/src/pkg/math/big/nat.go#L340

// alias returns true if x and y share the same base array.
func alias(x, y nat) bool {
    return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
}

In this example "nat" is a slice type, the same approach should also work with []byte or other slice types.

HTH,

Peter


--



Dumitru Ungureanu

unread,
Oct 15, 2012, 11:34:27 AM10/15/12
to golan...@googlegroups.com, Maxim Khitrov
So x is []Word.
What this is saying: &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1] ?

Basically, the general logic is that two slices x and y overlap if at least one slice element from x has the same memory address with one slice element from y... but I'm kind of lost to that syntax.

roger peppe

unread,
Oct 15, 2012, 11:40:57 AM10/15/12
to Dumitru Ungureanu, golan...@googlegroups.com, Maxim Khitrov
It's testing whether that very last element of each of the underlying arrays
has the same pointer. This is a sufficient test because a slice always
remembers its capacity, so you cannot make the last element in the underlying
array unavailable.

Maxim Khitrov

unread,
Oct 15, 2012, 11:41:27 AM10/15/12
to Peter S, golang-nuts
Much better, thanks! Here's the updated version of my code that no
longer requires unsafe and reflect:

http://play.golang.org/p/OXSfGvkC0y

Needs more testing, but I think I got the math right.

- Max

Maxim Khitrov

unread,
Oct 15, 2012, 11:45:05 AM10/15/12
to Dumitru Ungureanu, golan...@googlegroups.com
The two slices overlap if they both end at the same address. Once a
slice is created, you can move its starting address forward, but never
beyond start + capacity, which is a fixed value for any slice. That
syntax reslices x and y to their full capacity and takes the address
of the last element.

- Max

Dumitru Ungureanu

unread,
Oct 15, 2012, 11:48:05 AM10/15/12
to golan...@googlegroups.com, Dumitru Ungureanu
On Monday, October 15, 2012 6:45:44 PM UTC+3, Maxim Khitrov wrote:
The two slices overlap if they both end at the same address. Once a
slice is created, you can move its starting address forward, but never
beyond start + capacity, which is a fixed value for any slice. That
syntax reslices x and y to their full capacity and takes the address
of the last element.

- Max

The A-HA moment! Thank you.
Reply all
Reply to author
Forward
0 new messages