# panic: runtime error: cgo callback has unpinned Go pointer

- **ID:** `go/cgo-callback-gc-pin`
- **Domain:** go
- **Category:** runtime_error
- **Verification:** ai_generated
- **Fix Rate:** 80%

## Root Cause

Passing a Go pointer to a C function that stores it and later calls back, but the Go memory was not pinned, causing GC to move it.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| 1.22 | active | — | — |
| 1.23 | active | — | — |

## Workarounds

1. **Use `runtime.Pin` to pin the Go object before passing to C** (90% success)
   ```
   p := &myStruct{}
runtime.Pin(p)
defer runtime.Unpin(p)
C.callback(unsafe.Pointer(p))
   ```
2. **Allocate C memory and copy data** (85% success)
   ```
   cMem := C.malloc(C.size_t(unsafe.Sizeof(myStruct{})))
C.callback(cMem)
C.free(cMem)
   ```

## Dead Ends

- **Using `runtime.KeepAlive` after callback** — KeepAlive only prevents GC before the call, does not pin during C execution. (70% fail)
- **Making the pointer a global variable** — GC can still move global pointers if not pinned. (50% fail)
