程序调试随笔
来源:互联网 发布:java多线程写入数据库 编辑:程序博客网 时间:2024/06/05 17:28
技巧
__FILE__、__FUNCTION__、__LINE__
使用宏代替printf
输出乱码导致屏幕错乱
执行reset命令,还不行就只有重新login了
输出缓冲区问题
《UNIX环境高级编程》说:
标准出错绝不会是全缓冲的
当且仅当标准输出并不涉及交互作用设备时才是全缓存的
用fprintf(stderr…)
一定用printf的话
不重定向到文件
及时换行
fflush(stdout)强制刷新缓冲区
setbuf/setvbuf重设缓冲方式
一般不要用write(1,…),否则容易混乱
输出缓冲区问题
fflush(fp)
setbuf、setvbuf重设缓冲方式
用非缓冲API(write等)
一般不要混合使用缓冲型API与非缓冲型API,否则容易混乱
多执行流安全问题
最好每个执行流(线程/进程)写一个文件,不要重合
否则,争取每次LOG只调用一次write()
先snprintf整句LOG信息,再write一次
内存LOG
适用情况
运营中的系统
负载高、错误难以重现,直接LOG性能太低
原理
LOG时不写磁盘,而是写内存
当发现错误出现的时候才把LOG从内存写入磁盘
应对普通的逻辑错误(进程没有死)
平时把LOG写到内存中
一旦发现错误重现,则立刻把内存中的信息LOG到文件中
应对CoreDump
需要使用共享内存
平时
收到请求包时, LOG整个请求包的内容
处理过程中,可以LOG一些处理过程
发出回应包,准备收下个请求包时,清除内存LOG
启动时
如果共享内存里面有内容,则把该内容LOG到文件中
使用LOG到文件中的请求包进行分析
多数情况下,重发该包,就能直接跟踪出bug
strace/ltrace
分清系统调用和库函数
系统调用:Linux内核提供的API
库函数:运行时库提供的函数,也可以是系统调用的包裹函数(Wrapper)
功能
Strace:显示程序调用的系统调用
Ltrace: 显示程序调用的动态库的库函数
用途
Debug、性能分析、学习现有程序
重要参数
-p pid:attach现有进程
-e abc,xyz…:只跟踪指定的系统调用/库函数
-T –tt显示单个系统调用的开始时间、执行时间
GDB
跟踪变量写乱的一般步骤
Gdb attach后
Break设定断点(在该断点后,变量应该不会被改写)
Continue
到达上述断点后
Watch设定监控断点
Continue
程序修改该变量时,会中断回到gdb
Backtrace
打印各层函数栈的内容
如果不是预想中要修改该变量的代码,则找到该BUG了
大部分BUG可以通过上述步骤找到
如果找不到,则可能说明
该变量在共享内存,被另外一个执行流修改了
__FILE__、__FUNCTION__、__LINE__
使用宏代替printf
输出乱码导致屏幕错乱
执行reset命令,还不行就只有重新login了
输出缓冲区问题
《UNIX环境高级编程》说:
标准出错绝不会是全缓冲的
当且仅当标准输出并不涉及交互作用设备时才是全缓存的
用fprintf(stderr…)
一定用printf的话
不重定向到文件
及时换行
fflush(stdout)强制刷新缓冲区
setbuf/setvbuf重设缓冲方式
一般不要用write(1,…),否则容易混乱
输出缓冲区问题
fflush(fp)
setbuf、setvbuf重设缓冲方式
用非缓冲API(write等)
一般不要混合使用缓冲型API与非缓冲型API,否则容易混乱
多执行流安全问题
最好每个执行流(线程/进程)写一个文件,不要重合
否则,争取每次LOG只调用一次write()
先snprintf整句LOG信息,再write一次
内存LOG
适用情况
运营中的系统
负载高、错误难以重现,直接LOG性能太低
原理
LOG时不写磁盘,而是写内存
当发现错误出现的时候才把LOG从内存写入磁盘
应对普通的逻辑错误(进程没有死)
平时把LOG写到内存中
一旦发现错误重现,则立刻把内存中的信息LOG到文件中
应对CoreDump
需要使用共享内存
平时
收到请求包时, LOG整个请求包的内容
处理过程中,可以LOG一些处理过程
发出回应包,准备收下个请求包时,清除内存LOG
启动时
如果共享内存里面有内容,则把该内容LOG到文件中
使用LOG到文件中的请求包进行分析
多数情况下,重发该包,就能直接跟踪出bug
strace/ltrace
分清系统调用和库函数
系统调用:Linux内核提供的API
库函数:运行时库提供的函数,也可以是系统调用的包裹函数(Wrapper)
功能
Strace:显示程序调用的系统调用
Ltrace: 显示程序调用的动态库的库函数
用途
Debug、性能分析、学习现有程序
重要参数
-p pid:attach现有进程
-e abc,xyz…:只跟踪指定的系统调用/库函数
-T –tt显示单个系统调用的开始时间、执行时间
GDB
跟踪变量写乱的一般步骤
Gdb attach后
Break设定断点(在该断点后,变量应该不会被改写)
Continue
到达上述断点后
Watch设定监控断点
Continue
程序修改该变量时,会中断回到gdb
Backtrace
打印各层函数栈的内容
如果不是预想中要修改该变量的代码,则找到该BUG了
大部分BUG可以通过上述步骤找到
如果找不到,则可能说明
该变量在共享内存,被另外一个执行流修改了
- 程序调试随笔
- 随笔录之坚果手机调试安卓程序问题
- QDbus调试随笔1
- pixhawk 调试随笔
- 【经验随笔】Java程序远程调试定位特定运行环境上出现的问题
- C++程序随笔
- 程序人生随笔一
- 随笔-程序感悟
- C++程序随笔
- 程序随笔:汉诺塔
- 一个随笔画程序
- 微信小程序随笔
- 小程序学习随笔
- AJAX 简单例子调试随笔
- 窗体程序开发随笔收录
- 调试程序
- 程序调试
- 程序调试
- SQL STUFF函数 同一列值拼接 拼接字符串
- Jaxb2.0实现Java Object转换Xml转换Java Object.
- 命名空间
- Android判断一个Service是否运行 对服务的判断
- myeclipse插件介绍与下载
- 程序调试随笔
- POJ 2243 A*算法
- VB6.0分析access数据,生成excel文件
- FreeBSD内核锁机制(ZZ)
- C语言的复杂声明
- Linux 内核代码阅读 pid.c
- iOS开发知识要点
- 重新定义malloc和free 防止内存泄漏
- 如何编写一个安全的read函数