代码:
package main import "fmt" func test(x, y int) func() { return func() { x += y } } func main() { f := test(0x100, 0x200) f() fmt.Println("close") }
编译:
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
通过查看变量的内存地址,找到最终的相应变量,并且内存地址不在堆上,而是运行时。 newobject只分配一个似乎跟随的指针,并且不会继续指向该操作?