Go version
go version go1.25.0 darwin/arm64
Output of go env
in your module/workspace:
AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHEPROG=''
GODEBUG=''
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/7l/x6164vd11g73syllmzrm8nkc0000gp/T/go-build3087497557=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOOS='darwin'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.25.0/libexec'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.25.0/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.25.0'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
package main
import (
"fmt"
"io"
"net/http"
)
type (
A struct {
}
ArgsA struct {
URL string
}
)
func (a *A) MethodA(args *ArgsA) (string, error) {
resp, err := http.Get(args.URL)
if err != nil {
return "", nil
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", nil
}
return string(body), nil
}
type (
B struct {
a *A
}
ArgsB struct {
URL string
}
)
func (b *B) MethodB(args *ArgsB) error {
r, err := b.a.MethodA(&ArgsA{
URL: args.URL,
})
if err != nil {
return err
}
fmt.Println(r)
return nil
}
func main() {
b := &B{
a: &A{},
}
if err := b.MethodB(&ArgsB{
URL: "https://jsonplaceholder.typicode.com/posts",
}); err != nil {
panic(err)
}
}
There is a reproducer and a binary.
What did you see happen?
I launched debug session via default Run and Debug button at VS Code without launch.json
before MethodA
invocation, got expected value of args.URL
:
after MethodA
invocation, got unpredictable value. It can be "unreadable could not read string at 0x4 due to protocol error E08 during memory read for packet $m4", empty string or something like at screenshot below:
If don't call http.Get
and just return string synchronously or use the variable args
after http.Get
there won't be a problem, otherwise:
What did you expect to see?
I expect to see via debugger the same value of args
before and after method (where it was used) called.
PS It seems the problem happened when I updated golang to the latest version, previously it was 1.24.4 as I remember. Also I tried the same example at Windows laptop and it works fine. I already reported an issue at delve project. They said it probably has to do with compiler optimizations not debugger @aarzilli
Full Environment:
Delve Debugger Version: 1.25.1 Build: $Id: 4e95e55b6b38b12e8509c91ec55261df1f7ee38f Mac Sequoia 15.6.1 arm64 VS Code Version: 1.103.1 (Universal) Go for Visual Studio Code 0.48.0
Comment From: gabyhelp
Related Issues
- net/url: silent Segmentation fault. #51140 (closed)
- The debug result is different with go run result ( using unsafe. Pointer, got []byte cap = 0 and len >0 ) #40541 (closed)
- cmd/compile: Possible stack corruption when passing pointer to a "named return variable" to deferred function #13587 (closed)
- affected/package: net/http #49985 (closed)
- cmd/cgo: opaque struct pointers are broken since Go 1.15.3 #42032 (closed)
- cmd/compile: wrong line number generated after function call #47260 (closed)
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: adonovan
The "unreadable could not read string at %X due to protocol error" message seems like a Delve (debugger) issue.
The fact that the debugger cannot read a string out of args.URL seems like a liveness issue: the compiler may have decided the args
variable is no longer needed after the HTTP request and has reused the registers (or stack slot) for another purpose.