code:
package main import "fmt" func test(x, y int) func() { return func() { x += y } } func main() { f := test(0x100, 0x200) f() fmt.Println("close") }
compile:
go build -gcflags "-N -l" -o test main.go
gdb:
info "(gdb)Auto-loading safe path" (gdb) l 2 3 import "fmt" 4 5 func test(x, y int) func() { 6 return func() { 7 x += y 8 } 9 } 10 11 func main() { (gdb) l 12 f := test(0x100, 0x200) 13 f() 14 fmt.Println("close") 15 } (gdb) b 13 Breakpoint 1 at 0x483291: file /home/devops/study/src/function/closed_function.go, line 13. (gdb) b 6 Breakpoint 2 at 0x4831cc: /home/devops/study/src/function/closed_function.go:6. (2 locations) (gdb) r Starting program: /home/devops/study/src/function/test Breakpoint 2, main.test (x=256, y=512, ~r2={void ()} 0xc420043f20) at /home/devops/study/src/function/closed_function.go:6 6 return func() { (gdb) set disassembly-flavor intel (gdb) disassemble Dump of assembler code for function main.test: 0x0000000000483180 : mov rcx,QWORD PTR fs:0xfffffffffffffff8 0x0000000000483189 : cmp rsp,QWORD PTR [rcx+0x10] 0x000000000048318d : jbe 0x483240 0x0000000000483193 : sub rsp,0x28 0x0000000000483197 : mov QWORD PTR [rsp+0x20],rbp 0x000000000048319c : lea rbp,[rsp+0x20] 0x00000000004831a1 : mov QWORD PTR [rsp+0x40],0x0 0x00000000004831aa : lea rax,[rip+0x103af] # 0x493560 0x00000000004831b1 : mov QWORD PTR [rsp],rax 0x00000000004831b5 : call 0x40e3c0 0x00000000004831ba : mov rax,QWORD PTR [rsp+0x8] 0x00000000004831bf : mov QWORD PTR [rsp+0x18],rax 0x00000000004831c4 : mov rcx,QWORD PTR [rsp+0x30] 0x00000000004831c9 : mov QWORD PTR [rax],rcx => 0x00000000004831cc : lea rax,[rip+0x1e44d] # 0x4a1620 0x00000000004831d3 : mov QWORD PTR [rsp],rax 0x00000000004831d7 : call 0x40e3c0 # this wihle return a unsafe.Poniter 0x00000000004831dc : mov rax,QWORD PTR [rsp+0x8] 0x00000000004831e1 : mov QWORD PTR [rsp+0x10],rax 0x00000000004831e6 : lea rcx,[rip+0x133] # 0x483320 0x00000000004831ed : mov QWORD PTR [rax],rcx 0x00000000004831f0 : mov rax,QWORD PTR [rsp+0x10] 0x00000000004831f5 : test BYTE PTR [rax],al 0x00000000004831f7 : mov ecx,DWORD PTR [rip+0xc2de3] # 0x545fe0 0x00000000004831fd : mov rdx,QWORD PTR [rsp+0x18] 0x0000000000483202 : lea rdi,[rax+0x8] 0x0000000000483206 : test ecx,ecx 0x0000000000483208 : jne 0x483236 0x000000000048320a : jmp 0x48320c 0x000000000048320c : mov QWORD PTR [rax+0x8],rdx 0x0000000000483210 : jmp 0x483212 0x0000000000483212 : mov rax,QWORD PTR [rsp+0x10] 0x0000000000483217 : test BYTE PTR [rax],al 0x0000000000483219 : mov rcx,QWORD PTR [rsp+0x38] 0x000000000048321e : mov QWORD PTR [rax+0x10],rcx 0x0000000000483222 : mov rax,QWORD PTR [rsp+0x10] 0x0000000000483227 : mov QWORD PTR [rsp+0x40],rax 0x000000000048322c : mov rbp,QWORD PTR [rsp+0x20] 0x0000000000483231 : add rsp,0x28 0x0000000000483235 : ret 0x0000000000483236 : mov rax,rdx 0x0000000000483239 : call 0x44f5c0 0x000000000048323e : jmp 0x483212 0x0000000000483240 : call 0x44d170 0x0000000000483245 : jmp 0x483180 End of assembler dump. (gdb) c Continuing. Breakpoint 1, main.main () at /home/devops/study/src/function/closed_function.go:13 13 (gdb) x/16xg $rsp 0xc420043f10: 0x0000000000000100 0x0000000000000200 0xc420043f20: 0x000000c42000a060 0x000000000040423c 0xc420043f30: 0x000000c42005a058 0x0000000000000000 0xc420043f40: 0x000000c42000a060 0x00000000004b7465 0xc420043f50: 0x0000000000000000 0x0000000000000000 0xc420043f60: 0x000000c42000e1d0 0x000000c420043f78 0xc420043f70: 0x000000c42005a058 0x000000c420043f80 0xc420043f80: 0x0000000000427f32 0x000000c42005a000 (gdb) x/3xg 0x000000c42000a060 0xc42000a060: 0x0000000000483320 0x000000c420014098 0xc42000a070: 0x0000000000000200 (gdb) x/1xg 0x000000c420014098 0xc420014098: 0x0000000000000100
By looking at the address of the memory of the variable, the final corresponding variable is found, and the memory address is not on the heap, and the runtime. newobject only assigns a pointer that appears to follow and does not continue to point to the operation?