本人常用命令总结
readelf和nm
readelf -d gfqqg.so
① readelf -d gfqqg.so
读取 .dynamic 动态段 作用:
- 列出这个 so 运行时必须加载的其他 .so 依赖(DT_NEEDED)
- 查看 RPATH/RUNPATH、SONAME 链接路径 专门解决:
找不到 xxx.so加载报错。 这里看不到函数名。
nm gfqqg.so
② nm gfqqg.so
读取符号表 .symtab / .dynsym 作用:
- 列出库里面导出 / 导入的函数、全局变量符号 能看到:
- 本库对外提供的函数(T 文本段导出函数)
- 本库需要外部其他 so 提供的函数(U 未定义符号)
批量全部折叠代码快捷键
Cursor 官方已经调整了先导按键:Windows 端新版把 VSCode 原先Ctrl+K的前缀职能迁移成了Ctrl+M
- 批量全部折叠代码:
Ctrl+M再按下Ctrl+0 - 批量全部展开代码:
Ctrl+M再按下Ctrl+J
git克隆成功后切换绑定 v1.1 分支
cd tianji
git fetch origin
# 创建本地v1.1并自动关联远程
git checkout -b v1.1 origin/v1.1
# 验证追踪绑定
git branch -vv
git 临时储藏代码(切换分支不想提交半成品)
# 储藏所有改动
git stash
# 储藏并加备注
git stash save "临时储藏:C代码调试中"
# 查看储藏列表
git stash list
# 恢复储藏(不删除储藏记录)
git stash apply
# 恢复并删除储藏
git stash pop
# 删除储藏
git stash drop stash@{0}
git 修改最近的提交信息
修改最近一条提交信息
git commit --amend
如果你不是只改最近 1 条,而是改历史 N 条 commit,使用交互式 rebase:
# 修改最近3次提交记录,数字3代表最近3条
git rebase -i HEAD~3
弹出列表,把需要修改的 commit 前面的 pick 改成 r,保存退出,逐条执行 amend 修改。
- 只改文字用 r(reword)
- 要改代码用 e(edit)
- 不动就保持 pick
git 回退代码
git revert
1. 先查看提交日志,找到需要撤销的 commit ID
git log --oneline
# 输出示例:
# a567890 feat: 错误的功能提交(要撤销这条)
# b123456 fix: 修复登录bug
2. 执行 revert 撤销指定提交
# 撤销单条错误提交
git revert a567890
弹出编辑器,填写回退备注(如 revert: 撤销有bug的功能提交),保存退出。
3. 推送新生成的回退提交到远程公共分支
git push origin main
origin 是远程仓库的默认别名。
如果你要推 dev 分支,命令就写成 git push origin dev
当然也可以直接 git push (前提是当前分支已经关联远程分支)
可以通过git status 验证是否已经关联
Telnet
先开启 Windows 自带 Telnet 客户端
- Win+R 输入
optionalfeatures.exe回车 - 在弹出窗口勾选 Telnet 客户端 → 确定,等待安装完成,无需重启
telnet 10.80.79.168 22
- 连通成功:窗口黑屏,无任何报错,代表 22 端口能通;
- 不通 / 超时:提示
无法打开到主机的连接,在端口 22: 连接失败,和你现在 SSH 卡住的现象一致
查看环境变量
按字母排序输出,方便查找
env | sort # linux
Get-ChildItem Env: | Sort-Object Name # windows
设置环境变量
# 系统全局变量
[Environment]::SetEnvironmentVariable("MY_TOOL_PATH", "D:\tools\nm-bin", "Machine")
# 新建用户环境变量
[Environment]::SetEnvironmentVariable("MY_TOOL_PATH", "D:\tools\nm-bin", "User")
# 设置临时变量
$env:MY_TOOL_PATH = "D:\tools\nm-bin"
段错误后查询崩溃地址
执行 ulimit -c 查看默认 默认是0
ulimit -c
0
数值为 0 的含义:禁止生成任何 core 文件。
- dmesg 内核环形缓冲区 不受 ulimit 控制,只要发生段错误,内核一定会写入一行极简日志(崩溃 IP 地址、非法访问地址),只有地址,没有完整代码 / 变量;
- core 转储文件 由
ulimit -c开关控制,是完整内存镜像,能看调用栈、局部变量、指针值,深度排查必备。
步骤 1:基础前置,编译带调试符号
gcc -g -O0 test.c -o test
-g调试信息,用于 gdb/asan/addr2line;-O0关闭优化,防止编译器重排代码导致栈错乱。
-g 告诉 gcc 在可执行文件里附加一套调试信息:
- 源码文件路径、每一行代码对应的机器码地址;
- 全局变量、局部变量名、变量类型;
- 函数名、参数、栈帧映射关系
步骤 2:优先用最快精准工具定位根源(主力工具,nm 不在这里)
场景 A:必现崩溃,想要最详细内存违规原因
使用 ASAN(地址消毒器,AI 调试首选)
gcc -g -fsanitize=address test.c -o test
./test
直接输出:越界 / 野指针 / 重复 free + 精确文件行号,一步锁定代码,90% 简单段错误到此解决。
场景 B:无 asan 环境、传统调试
- 生成 core 转储文件,捕获崩溃现场
ulimit -c unlimited
./test
- gdb 加载 core 查看调用栈
gdb ./test core.xxxx
bt full
拿到崩溃函数、代码行、局部变量、指针值。
场景 C:偶现、内存破坏、堆污染(asan 查不出)
valgrind 内存检测,缓慢但能捕获隐性越界。
步骤 3:nm 介入辅助验证(定位到函数后,校验符号异常)
拿到崩溃函数名 crash_func,执行:
# C项目
nm test | grep crash_func
# C++项目,解码混淆符号
nm -C test | grep crash_func
根据输出判断三类符号异常:
- 输出
U crash_func:未定义符号,链接缺失库,运行跳转空指针崩溃; - 无任何输出:函数被优化删除、名字写错;
- 多条
T crash_func:多重定义,链接冲突,跑错函数逻辑; - 小写
t crash_func:static 静态函数,外部非法调用。
步骤 4:无调试符号 / 生产环境无 gdb,离线定位(nm + dmesg + addr2line)
- 内核日志拿崩溃指令地址:
dmesg | grep segfault
# ip 后数字 = 崩溃地址
- addr2line 将地址转为代码行:
addr2line -e ./test 0xxxxxxx
- nm 反查该地址对应的函数,确认是否匹配日志栈信息:
nm test | grep 0xxxxxxx
步骤 5:静态二进制兜底排查(无源码、只有程序)
objdump -dC反汇编崩溃函数汇编;nm查看依赖的外部函数、全局变量;strings提取程序日志字符串辅助缩小范围
ASan 是什么
AddressSanitizer 是 GCC/Clang 内置的内存错误检测工具,专门捕获 C/C++ 所有内存越界类崩溃,比 gdb 手动抓段错误高效得多。
能自动查出的问题:
- 堆溢出、栈溢出、全局数组越界读写
- 野指针、空指针解引用
- 重复 free、释放后再使用(use-after-free)
- 内存泄漏(搭配
detect_leaks=1) - 栈缓冲区溢出、返回后栈变量复用
和普通 gdb 的区别
- gdb:程序崩溃那一刻才停,只能看现场;
- ASan:每一次非法内存访问立刻中断,直接打印完整栈、源码行号、错误类型,不用手动
ulimit -c+ core + addr2line 整套流程。
查找名叫"30943"的目录
find / -type d -name "30943" 2>/dev/null
注意 "2"表示标准错误,/dev/null是黑洞文件
更多推荐


所有评论(0)