📄 037.htm
字号:
<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=GB2312"><TITLE>-->Linux HowTo 中译版-->The Linux GCC HOWTO中译版V0.1: Debugging and Profiling</TITLE>
<META NAME="keywords" CONTENT=" Linux HowTo 中译版 The Linux GCC HOWTO中译版V0.1: Debugging and Profiling">
<META NAME="description" CONTENT=" - Linux HowTo 中译版 - The Linux GCC HOWTO中译版V0.1: Debugging and Profiling">
<style>
<!--
#page {position:absolute; z-index:0; left:0px; top:0px}
.tt3 {font: 9pt/12pt "宋体"}
.tt2 {font: 12pt/15pt "宋体"}
a {text-decoration:none}
a:hover {color: blue;text-decoration:underline}
-->
</style>
</HEAD>
<body text="#000000" aLink=#9900ff link=#006699 vLink=#006699 bgcolor="#FFFFFF" leftmargin="3" topmargin="3" marginheight="3" marginwidth="3">
<TABLE WIDTH="100%" CELLPADDING=10 CELLSPACING=0 BORDER=0>
<TR>
<TD CLASS="tt3" VALIGN="top" width="8%" bgcolor="#e0e0e0"><strong><A HREF="038.htm">后一页</A><BR>
<A HREF="036.htm">前一页</A><BR>
<A HREF="index.html">回目录</A><BR>
<A HREF="../../../../index.htm">回首页</A><BR>
</strong>
</TD>
<TD class="tt2" bgcolor="#F5F8F8" width="84%"><center><B><FONT style="FONT-SIZE: 16.5pt" COLOR="#FF6666" FACE="楷体_GB2312">The Linux GCC HOWTO中译版V0.1: Debugging and Profiling</FONT></B></center>
<hr color="#EE9B73" size="1" width="94%">
姓名:Daniel Barlow<br>
Email:dan@detached.demon.co.uk<br>
地址 :<br>
转摘 :http://member.netease.com/</p>
<BR>
<BR>
<hr SIZE="0">
<BR>
<p><br>
<br>
5. Debugging and Profiling <br>
5.1. Preventative maintenance (lint) <br>
lint对Linux而言并没有很广泛的用途,主要是因为大部份的人都能满足於gcc所提供的警告讯息(warnings).可能最有用的就是-Wall参数了---这个参数的用途是要求gcc将所有的警告讯息显现出来.but
probably has more mnemonic value if thought of as the thing you bang your head against. <br>
<br>
网路上有一个实用的public domain lint,位於
ftp://larch.lcs.mit.edu/pub/Larch/lclint.我并不知道这个站到底有多好就是了.
<br>
<br>
5.2. 除错(Debugging) <br>
5.2.1. 我要怎样做才能将除错资讯放到一支程式里头? <br>
你需要添加-g的参数来编译与连结程式,而且不可以用-fomit-frame-pointer参数.事实上,你不需要重新编译所有的程式,只需重新编译目前你正在除错的部份即可.
<br>
<br>
就a.out的格式(configurations)而言,共享程式库(shared libraries)是以-fomit-frame-pointer编译而成,这个时候,gdb就变得英雄无用武之地了.连结时给定-g的选项,应该就隐含著静态连结(static
linking)了;这就是为什麽要加-g的原因了. <br>
<br>
如果连结器(linker)连结失败,告诉你找不到libg.a,那就是在/usr/lib/的目录底下,少了libg.a.libg.a是特殊的C语言侦错程式库(special
debugging-enabled C library).一般在libc的套件内就会提供libg.a;不然的话(新版是这样的),你可能需要拿libc的原始码自己建立了.不过,实际上你应该不需要才对.不管是什麽目的,大部份的情况下,只需将libg.a连结到/usr/lib/libc.a,你就能得到足够的资讯了.
<br>
<br>
5.2.1.1. 那,能不能把除错资讯给拿掉? <br>
很多的GNU软体在编译连结时,都会设定-g的选项,而这样做会造成执行档过大的问题(通常是静态的).实际上,这并不是一个很热门的想法.
<br>
<br>
如果程式本身有autoconf,产生了configure命令稿,通常你就可以用./configure
CFLAGS=或是./configure CFLAGS=-O2来关掉除错资讯.不然的话,你得检查检查Makefile了.当然啦,假如你用的是ELF,程式便会以动态的方式连结(dynamically
linked),不论是否有-g的设定;因此你可以平常心把-g拿掉(strip). <br>
<br>
5.2.2. 实用的软体(Available software) <br>
据了解,一般人都使用gdb.你可以从GNU archive sites拿到原始程式;或者是到tsx-11拿可执行档.xxgdb是一个X介面的除错程式(debugger),植基於gdb(也就是说你得先安装好gdb,才能再装xxgdb).xxgdb的原始码可以在ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz找到.
<br>
<br>
另外,UPS除错程式已由Rick Sladkey移植成功.UPS可以在X底下活得很好,不像xxgdb那样---仅仅是gdb的X前端介面(X
front end).这支除错程式有一大堆优良的特点,and if you spend any time
debugging stuff, you probably should check it out.先前编译(precompiled)好的Linux版与修正版(patches)的原始码可以在ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/找到.而最初的原始程式则放在
ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z. <br>
<br>
你可能会发现另一个用来除错的工具strace,也是相当的有用.它可以显示出由程序(process)所产生的系统呼叫,而且还拥有其它众多繁复的功能(multiplicity),像是如果你手边没有原始码的话,strace可以帮你找出(figure
out)有那些路径(path-names)已编译进执行档(binaries)内; exacerbating race
conditions in programs that you suspect contain them;还有,strace可拿来学习程式是怎麽在电脑中执行的.最新的版本(目前是3.0.8)可在找到ftp://ftp.std.com/pub/jrs/.
<br>
<br>
5.2.3. 背景程式(Background (daemon) programs) <br>
早期典型的常驻程式(daemon programs)是执行fork(),然後终止(terminate)父程序(parent).这样的做法使得除错的时间减短了.
<br>
<br>
了解(get around)这点的最简单的方法就是替fork()设一个breakpoint.当程式停止时,强迫fork()传回0.
<br>
<br>
<br>
(gdb) list <br>
1 #include <stdio.h> <br>
2 <br>
3 main() <br>
4 { <br>
5 if(fork()==0) printf("child\n"); <br>
6 else printf("parent\n"); <br>
7 } <br>
(gdb) break fork <br>
Breakpoint 1 at 0x80003b8 <br>
(gdb) run <br>
Starting program: /home/dan/src/hello/./fork <br>
Breakpoint 1 at 0x400177c4 <br>
<br>
Breakpoint 1, 0x400177c4 in fork () <br>
(gdb) return 0 <br>
Make selected stack frame return now? (y or n) y <br>
#0 0x80004a8 in main () <br>
at fork.c:5 <br>
5 if(fork()==0) printf("child\n"); <br>
(gdb) next <br>
Single stepping until exit from function fork, <br>
which has no line number information. <br>
child <br>
7 } <br>
<br>
<br>
5.2.4. 核心档案(Core files) <br>
当Linux开机时,通常组态(configuration)会设定成不要产生核心档案.要是你那麽喜欢它们的话,可以用shell的builtin命令使其重新生效:就C-shell相容的shell(如tcsh)而言,会是下面这样:
<br>
<br>
% limit core unlimited <br>
<br>
而类似Bourne shell的shell(sh,bash,zsh,pdksh)则使用下面的语法: <br>
$ ulimit -c unlimited <br>
<br>
<br>
如果你想要有个多才多艺(versatility)的核心档命名(core file naming)(for
example, if you're trying to conduct a post-mortem using a debugger that's buggy itself) ,那麽你可以对你的核心程式(kernel)做一点小小的更动(mod).找一找fs/binfmt_aout.c与fs/binfmt_elf.c档内与下列相符的程式片段(in
newer kernels, you'll have to grep around a little in older ones): <br>
<br>
<br>
memcpy(corefile,"core.",5); <br>
#if 0 <br>
memcpy(corefile+5,current->comm,sizeof(current->comm)); <br>
#else <br>
corefile[4] = '\0'; <br>
#endif <br>
<br>
<br>
将0换成1. <br>
<br>
5.3. 旁敲侧击(Profiling) <br>
Profiling是用来检核一支程式中那些部份(which bits)是最常呼叫或是执行的时间最久的方法.这对程式的最佳化与找出何时时间是浪费掉的而言,是相当好的方式.你必须就你所要的时程资讯(timing
information)的目的档案(object files)加上-p来编译,而且如果要让输出的档案(output
files)有意义(make sense),你也会需要gprof(来自binutils套件的命令).参阅gprof的manual
page,可得知其细节. <br>
<br>
11/18/97译 <br>
</p>
<BR>
<hr color="#EE9B73" size="1" width="94%">
</TD>
<TD CLASS="tt3" VALIGN="bottom" width="8%" bgcolor="#e0e0e0"><strong><A HREF="038.htm">后一页</A><BR>
<A HREF="036.htm">前一页</A><BR>
<A HREF="index.html">回目录</A><BR>
<A HREF="../../../../index.htm">回首页</A><BR>
</strong>
</TD>
</TR>
</table>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -