Fix unsafe use of pointers in sample code #16
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
benchmark_marshaler_test.go and its copy in the README demonstrated
unsafe conversion of uintptr -> unsafe.Pointer. Fixing this will
hopefully reduce the likelihood that users will write unsafe code.
I noticed the unsafety while reading this blog post, which says:
As I understand, the reason that the old version was unsafe and this is not is that Go reserves the right for the garbage-collector to move objects, which may invalidate the uintptr pointing to the struct field before the field can be accessed. However, by doing the conversion to a uintptr, the pointer arithmetic, and the conversation back to an unsafe.Pointer in one statement, the value retains its pointer semantics through the whole operation and is guaranteed to be updated if the underlying object is moved.
(I don't believe the current GC actually moves objects, so probably the old version would always work... unless / until a new version of Go introduces this, at which point something like this could cause very rare breakages.)
Even though this code is meant as a benchmark and sample use-case, since users will try to copy this code to write similar code, it's probably best to demonstrate good practices that won't break in the future.
go vet
validates that the old version was unsafe and the new version is not. Running the benchmark with the old and new versions of the code seemed to show equivalent performance and no additional allocations.