Why runtime.KeepAlive(x) is need here

hello, I found the code in the std source code;
I am confused by the runtime.KeepAlive(x) call;
Can anyone tell me why it needed here;
As far as I know, verifyGCInfo refernces the x by &x; so it’s seems unnecessarily here.

{
	var x string
	verifyGCInfo(t, "stack string", &x, infoString)
	runtime.KeepAlive(x)
}

func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) {
    mask := runtime.GCMask(p)
    if !bytes.Equal(mask, mask0) {
	    t.Errorf("bad GC program for %v:\nwant %+v\ngot  %+v", name, mask0, mask)
	    return
    }
}
2 Likes

That’s part of the runtime test code, testing implementation specifics of the GC using undocumented runtime functions… in other words there are dragons here and we (I) don’t understand what is being tested. Maybe the test checks whether the thing is expected to be alive after the function returns. :man_shrugging:

In normal code you don’t need to call keep alive under the quoted circumstances.

2 Likes

GCMask returns type mask of struct fields (scalar (0) or pointer (1)).
If data of string (string are 2 field struct with data and len) are being unused after its call then GCMask will return scalar type for data otherwise pointer type (always if it heap allocated).

infoString is just []byte{typePointer, typeScalar}

So, data of string is actually unused and stack allocated (it must return scalar type), but runtime.KeepAlive force it be used and GCMask will return []byte{1, 0} (which equals infoString) instead of []byte{0, 0}.

here’s playground for tests: https://play.golang.org/p/FCewUguUoLB


And about &x and x - GCMask requires pointer to variable because it actually reads gc info of specific one (x is just a copy of).

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.