惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
IT之家
IT之家
V
V2EX
Jina AI
Jina AI
V
Visual Studio Blog
有赞技术团队
有赞技术团队
博客园 - 司徒正美
博客园 - 叶小钗
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Google DeepMind News
Google DeepMind News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
腾讯CDC
Google Online Security Blog
Google Online Security Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
N
News and Events Feed by Topic
N
News and Events Feed by Topic
The Last Watchdog
The Last Watchdog
W
WeLiveSecurity
月光博客
月光博客
Security Archives - TechRepublic
Security Archives - TechRepublic
Webroot Blog
Webroot Blog
SecWiki News
SecWiki News
博客园_首页
罗磊的独立博客
量子位
Latest news
Latest news
I
Intezer
V
Vulnerabilities – Threatpost
A
Arctic Wolf
Last Week in AI
Last Week in AI
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
SegmentFault 最新的问题
S
Security Affairs
阮一峰的网络日志
阮一峰的网络日志
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
N
News | PayPal Newsroom

ZDDHUB

PixelsMeasure 开发第二年总结 PixelsMeasure 开发一年总结 Swift/SwiftUI 踩坑记 为什么说 GPT 利好程序员 ChatGPT 编程实现 Web 数字水印 Web 数字水印探究 Micro Frontends for Mobile URL 加载系统(URL Loading System) Protocol Buffers GraphQL 从 0 到 1 开发一款 IOS 应用 - Swift MV* 软件设计架构 学习一个新技巧需要多久? 不停机数据库迁移 Rspec 如何 mock update 方法更新自己? Rails 使用 mysql2 出现的段错误 使用 Docker-compose 部署 Rails 应用到生产环境 Cocoa troubleshooting 独孤九剑 Dit (0x05) - 终端篇 Gem-based Jekyll theme 开发小记 Miscellaneous 前端手记 TodoMVC 之 Redux 篇 前端手记 TodoMVC 之 Server 篇 前端手记 TodoMVC 之 React 篇 前端手记 TodoMVC 之 CSS 篇 独孤九剑 Dit (0x04) - 测试篇 独孤九剑 Dit (0x03) - 缓存篇 英语小抄 Make mistakes 大牛俱乐部上线啦 独孤九剑 Dit (0x02) - 数据结构篇 独孤九剑 Dit (0x01) - 总决 独孤九剑 Dit (0x00) - 我为什么要做 Dit 零值强制类型转换的使用 终端颜色输出重定向 Go语法简略 - 正则表达式 Makefile Go语法简略 - Duck框架探索 Go语法简略 - 依赖注入 Go语法简略 - web应用框架 Go语法简略 - 反射 Go语法简略 - 面向对象 Go语法简略 - goroutine Go语法简略 - 方法和接口 Go语法简略 - 基础篇 大牛 轻松科研 未来这几年 为 Android Studio 创建图标 Shell Git Vim 金庸答百问 论拖延症 Flex, A fast scanner generator 有理想的人 从虚拟到现实 常用视频转接口 Recognizer configuration on CentOS 整个世界清静了 《Python源码剖析》读书笔记
LLDB debug Golang
zddhub · 2015-12-20 · via ZDDHUB

除了 GDB,还可以使用 LLDB debug go code

熟练调试工具是程序员的必备技能,lldb 的发展势头,大有取缔 gdb 的趋势,因此需要把 lldb 加入到自己的工具箱里。

LLDB 命令

LLDB 的所有命令都遵从以下格式:

<noun> <verb> [-options [option-value]] [argument [argument...]]

对于常用命令,可设置别名,降低输入负担。(可通过别名设置和 GDB 相同的语法,降低记忆负担)。

常用命令集

go build -gcflags "-N -l" -o test test.go 关闭编译优化
b test.go:10    设置断点,如果项目中存在同名文件,会根据行号对应的内容选择一个,或者两个都选
run             运行到断点处
n               运行到下一行
ni              回到当前运行的代码片段
p varname       打印变量值
frame variable  打印当然 frame 中的所有变量
r               重新运行程序

LLDB 练习

以下通过一个例子程序的调试,了解 LLDB 的基本用法。待调试程序如下:

package main

import (
  "fmt"
  "time"
)

func counting(c chan<- int) {
  for i := 0; i < 10; i++ {
    time.Sleep(1 * time.Second)
    c <- i
  }
  close(c)
}

func main() {
  msg := "Starting main"
  fmt.Println(msg)
  bus := make(chan int)
  msg = "starting a gorountie"
  go counting(bus)
  for count := range bus {
    fmt.Println("count:", count)
  }
}

编译源码,使用 -gcflags "-N -l" 参数关闭编译器代码优化。

$ go build -gcflags "-N -l" -o test test.go

通过 lldb 命令启动调试:

可通过 run (r) 运行整个程序,如下所示,和我们在终端运行命令结果一致。

(lldb) run
Process 3242 launched: '/Users/zdd/Projects/Go/src/github.com/zddhub/test/test' (x86_64)
Starting main
count: 0
count: 1
count: 2
count: 3
count: 4
count: 5
count: 6
count: 7
count: 8
count: 9
Process 3242 exited with status = 0 (0x00000000)
(lldb)

断点命令

(lldb) breakpoint set --file test.go --line 17
(lldb) b test.go:17 #简写

为程序设置断点并查看断点,

(lldb) b test.go:10
Breakpoint 1: where = test`main.counting + 43 at test.go:10, address = 0x000000000000206b
(lldb) b test.go:23
Breakpoint 2: where = test`main.main + 514 at test.go:23, address = 0x00000000000022f2
(lldb) br list
Current breakpoints:
1: file = 'test.go', line = 10, locations = 1
  1.1: where = test`main.counting + 43 at test.go:10, address = test[0x000000000000206b], unresolved, hit count = 0

2: file = 'test.go', line = 23, locations = 1
  2.1: where = test`main.main + 514 at test.go:23, address = test[0x00000000000022f2], unresolved, hit count = 0

运行一次到第一个断点

(lldb) run
Process 3302 launched: '/Users/zdd/Projects/Go/src/github.com/zddhub/test/test' (x86_64)
Starting main
Process 3302 stopped
* thread #1: tid = 0x11ca78, 0x000000000000206b test`main.counting(c=0x000000c820070000) + 43 at test.go:10, stop reason = breakpoint 1.1
    frame #0: 0x000000000000206b test`main.counting(c=0x000000c820070000) + 43 at test.go:10
   7
   8    func counting(c chan<- int) {
   9      for i := 0; i < 10; i++ {
-> 10       time.Sleep(1 * time.Second)
   11       c <- i
   12     }
   13     close(c)
(lldb)

之后,通过 cn 继续运行程序。

查看变量的值:

* thread #10, stop reason = breakpoint 3.1
    frame #0: 0x0000000001093939 xx`main.counting(c=0x000000c420076060) at xx.go:10
   7
   8    func counting(c chan<- int) {
   9      for i := 0; i < 10; i++ {
-> 10       time.Sleep(1 * time.Second)
   11       c <- i
   12     }
   13     close(c)
(lldb) p i
(int) i = 0
(lldb) p c
(chan<- int) c = 0x000000c420076060

查看当前 frame 中的所有变量

(lldb) frame variable
(chan<- int) c = 0x000000c420076060
(int) i = 0
([]*runtime.g) runtime.allgs = (len 5, cap 8) {
  [0] = 0x000000c420000180
  [1] = 0x000000c420000600
  [2] = 0x000000c420000a80
  [3] = 0x000000c420000f00
  [4] = 0x000000c420001080
}

命令 ni 回到当前断点所在的代码片段

(lldb) ni
Process 35396 stopped
* thread #10, stop reason = instruction step over
    frame #0: 0x0000000001093941 xx`main.counting(c=0x000000c420076060) at xx.go:10
   7
   8    func counting(c chan<- int) {
   9      for i := 0; i < 10; i++ {
-> 10       time.Sleep(1 * time.Second)
   11       c <- i
   12     }
   13     close(c)

watch 变量的值:

(lldb) watch set var i
Watchpoint created: Watchpoint 1: addr = 0xc820026798 size = 8 state = enabled type = w
    watchpoint spec = 'i'
    new value: 0
(lldb) c
Process 3302 resuming

Watchpoint 1 hit:
old value: 0
new value: 1
Process 3302 stopped
* thread #1: tid = 0x11ca78, 0x00000000000020be test`main.counting(c=0x000000c820070000) + 126 at test.go:9, stop reason = watchpoint 1
    frame #0: 0x00000000000020be test`main.counting(c=0x000000c820070000) + 126 at test.go:9
   6    )
   7
   8    func counting(c chan<- int) {
-> 9      for i := 0; i < 10; i++ {
   10       time.Sleep(1 * time.Second)
   11       c <- i
   12     }
(lldb)

列举所有观测变量:

(lldb) watch list -v
Number of supported hardware watchpoints: 4
Current watchpoints:
Watchpoint 1: addr = 0xc820026798 size = 8 state = enabled type = w
    watchpoint spec = 'i'
    old value: 0
    new value: 1
    hw_index = 0  hit_count = 1     ignore_count = 0
Watchpoint 2: addr = 0xc8200267b8 size = 8 state = enabled type = w
    watchpoint spec = 'c'
    new value: 0x000000c820070000
    hw_index = -1  hit_count = 0     ignore_count = 0
(lldb)
(lldb) fr v
(long) i = 2
(chan<- int) c = 0x000000c820070000

如果你喜欢这篇文章,欢迎赞赏作者以示鼓励