本文讲的是不编译完全release的可执行文件,而是使用cmake的RelWithDebugInfo(附加调试信息的编译,它的效果下面会说明)或者Debug编译也可以生成release版本的可执行文件进行调试.
详细的 cmake 使用会在下一篇文章里讲.
这里先记下Debug, Release 和 RelWithDebugInfo的区别(对比我手上的gcc 4.8.2编译出的不同版本得出的结论)
- Debug 等同于 -O0 -g 编译选项, 不优化代码, 附加调试信息
- Release 等同于 -O3 编译选项, 最大化优化代码, 但不包含调试信息
- RelWithDebugInfo 等同于 -O2 -g 编译选项, 中等程度优化代码, 并且包含调试信息.
可以自定义使用-O3 -g 的编译选项,来生成最接近Release的代码(至于-ggdb的选项,加了以后二进制只大了8个字节,目测无所谓)
下面的方法只对-g编译有效,方法有两种.
man手册里推荐的方法
- objcopy –only-keep-debug foo foo.dbg 把调试信息(即debug section)dump到单独的文件里.
- objcopy –strip-debug foo 这里只剔除调试信息,符号信息仍保留(用户依然可以用nm查看到各种函数符号,我推荐用–strip-all,连同符号信息一起删除,生成的可执行文件更小,不影响调试)
- objcopy –add-gnu-debuglink=foo.dbg foo 为foo添加.gnu-debuglink section, 这个会让二进制增加近100字节的样子.
这样分离了Debug Section后,就可以单独分发release版本的foo,调试时只需讲foo.dbg放在和foo同一目录下即可直接gdb foo进行调试.
如果不希望Release的最终二进制文件包含.gnu-debuglink段,那么可以直接省略第三步,且当成另一种方法,方便叙述.
- 同一
- strip foo 这个效果等同于objcopy –strip-all foo,剔除所有符号和调试信息, 即为release版本.
方法二所不同的调试方法是需先加载dbg文件, gdb foo.dbg, 然后attach(或者exec)到foo进程,这样不要求.dbg和执行程序在同一个目录下,并且适合调试已经启动的进程,例如服务器.