Skip to content
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

fmt: bad pointer in frame fmt.(*pp).printValue #64111

Closed
gucio321 opened this issue Nov 14, 2023 · 8 comments
Closed

fmt: bad pointer in frame fmt.(*pp).printValue #64111

gucio321 opened this issue Nov 14, 2023 · 8 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@gucio321
Copy link
Contributor

What version of Go are you using (go version)?

$ go version
go version go1.21.4 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/my-username/.cache/go-build'
GOENV='/home/my-username/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/my-username/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/my-username/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.4'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build497266722=/tmp/go-build -gno-record-gcc-switches'

What did you do?

I'm writting a wrapper of C void* pointer via CGO. I'm getting the following panic:

runtime: bad pointer in frame fmt.(*pp).printValue at 0xc00022d758: 0x1
fatal error: invalid pointer found on stack

Code causing this looks as follows:

        v := texture.ID()
        fmt.Println("%T\n", v)

BUT when I add this single line:

        fmt.Println(texture)
        v := texture.ID()
        fmt.Println("%T\n", v)

This works perfectly.

Full project (as I'm unable to extract a single reproduction code) is here:
https://github.com/gucio321/cimgui-go/tree/callbacks

What did you expect to see?

No panic should happen

What did you see instead?

Panic

@ericlagergren
Copy link
Contributor

Any sort of repro would be helpful.

Out of curiosity, what happens when you add runtime.KeepAlive(texture) after the call to fmt.Println in your first code snippet?

Also, fyi: fmt.Println doesn't accept format specifiers.

@gucio321
Copy link
Contributor Author

Also, fyi: fmt.Println doesn't accept format specifiers.

oh, sorry, its a typo ofc. I meant Printf, but it doesn't matter in fact. The problem is with the value returned by texture.ID() which returns unsafe.Pointer representing C void* pointer

Out of curiosity, what happens when you add runtime.KeepAlive(texture) after the call to fmt.Println in your first code snippet?

nothing changes

Any sort of repro would be helpful.

I know, I tried to write some code but with no result.

Also, I tried to use go-delve to debug this but with no result - when using debugger it worked fine...

@mauri870 mauri870 added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Nov 14, 2023
@gucio321
Copy link
Contributor Author

in fact, reproducable code is here: https://github.com/gucio321/cimgui-go/tree/callbacks
I tried to write something myself but it didn't work as expected
Generally speaking the idea looks as follows:

  • C creates a void* pointer
  • go takes it as an unsafe.pointer
    here are some code pieces:
type Texture struct {
        id     TextureID
        Width  int
        Height int
}

func NewTextureFromRgba(rgba *image.RGBA) *Texture {
        texID := textureManager.CreateTextureRgba(rgba, rgba.Bounds().Dx(), rgba.Bounds().Dy())

        if texID.Data == nil {
                return nil
        }

        texture := Texture{
                id:     texID,
                Width:  rgba.Bounds().Dx(),
                Height: rgba.Bounds().Dy(),
        }

        // Set finalizer
        runtime.SetFinalizer(&texture, (*Texture).release)

        return &texture
}

func (t *Texture) release() {
        textureManager.DeleteTexture(t.id)
}

func (t *Texture) ID() TextureID {
        return t.id
}

type TextureID struct {
        Data unsafe.Pointer
}

func (self *TextureID) handle() (*C.ImTextureID, func()) {
        result, fn := self.c()
        return &result, fn
}

func (selfStruct *TextureID) c() (result C.ImTextureID, fin func()) {
        self := selfStruct.Data
        selfArg, selfFin := WrapVoidPtr(self)
        return (C.ImTextureID)(selfArg), func() { selfFin() }
}

func newTextureIDFromC(cvalue *C.ImTextureID) *TextureID {
        v := (unsafe.Pointer)(*cvalue)
        return &TextureID{Data: unsafe.Pointer(v)}
}

@bcmills
Copy link
Contributor

bcmills commented Nov 14, 2023

0x1 is almost certainly not a valid pointer. Per the C11 spec, “the result [of converting an integer to a pointer type] is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.” It just so happens that 0x1 acts as a trap representation for the Go runtime.

If you have a C type that may represent a mix of pointers and integers, you should generally pass it to Go as a uintptr rather than a void*.

@bcmills bcmills added the compiler/runtime Issues related to the Go compiler and/or runtime. label Nov 14, 2023
@mknyszek mknyszek added this to the Backlog milestone Nov 15, 2023
@mknyszek
Copy link
Contributor

@gucio321 Is there anything to follow-up with here? Closing optimistically, but please comment if you disagree. Thanks!

@mknyszek mknyszek closed this as not planned Won't fix, can't repro, duplicate, stale Nov 22, 2023
@gucio321
Copy link
Contributor Author

@mknyszek After reading @bcmills's statement I still think that fmt shouldn't care what exactly is the pointer as it (in theory) could be whatever the programmer wants - even 0x1 (because why not? - its the idea of the unsafe package). So in my opinion using uintptr is a good workaround here but I think that this panic is a bug in go that should be fixed, shouldn't it?

@gucio321
Copy link
Contributor Author

CC @mknyszek

@gucio321
Copy link
Contributor Author

Also, using uintptr is in fact not a good solution at all since it violates race detector rules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

5 participants