| Profil de Libin绿色家园PhotosBlogListes | Aide |
|
29 juin Windows VC6编译安装Boost库首先从Boost的老巢http://www.boost.org/下载。下载完成以后是一个安装文件(其实就是进行自动解压缩的)。选择你的目录解压缩Boost库。然后我们开始对其进行编译我所下载的版本是1.33.1。
1.cmd
2.进入安装VC的目录例如c:\Program Files\Microsoft Visual Studio\VC98\Bin目录
3.运行VCVARS32.BAT(这个操作的作用是对此控制台注册VC的环境变量,这样我们就可以在任意目录使用cl进行编译程序)。
4.进入Boost的目录例如c:\boost_1_33_1\tools\build\jam_src
5.修改build.bat脚本的参数(如果必要的话,你的安装目录不是c:盘)
将原参数
if EXIST "C:\Program Files\Microsoft Visual Studio\VC98\bin\VCVARS32.BAT" (
set BOOST_JAM_TOOLSET=msvc set BOOST_JAM_TOOLSET_ROOT=C:\Program Files\Microsoft Visual Studio\VC98\ goto :eof) 修改为(就是你的VC6.0安装的目录,我这里举个例子)
if EXIST "D:\Program Files\Microsoft Visual Studio\VC98\bin\VCVARS32.BAT" (
set BOOST_JAM_TOOLSET=msvc set BOOST_JAM_TOOLSET_ROOT=D:\Program Files\Microsoft Visual Studio\VC98\ goto :eof) 6.在刚才打开的控制台下运行
D:\d\boost_1_33_1\tools\build\jam_src\build.bat
最终会在目录下生成一个名为bin.ntx86的文件夹里面包含一个bjam.exe可执行文件,将其拷贝到D:\boost_1_33_1目录下
7.安装python可以在www.python.org获得
8.设置环境变量
SET MSVC_ROOT="c:\Program Files\Microsoft Visual Studio\VC98"
SET VISUALC="c:\Program Files\Microsoft Visual Studio\VC98" SET JAM_TOOLSET=VISUALC SET PYTHON_ROOT=D:\Program Files\Python23 SET PYTHON_VERSION=2.3 9开始编译
bjam -sTOOLS=msvc install(将会安装在默认目录C:\Boost)
这样编译就完成了
10.boost类库在VC6.0的IDE环境中的配置
Tools" -> "Options" -> "Diretories" -> "Show Diretories for"中的下拉框选择:
1) 在Include files 中添加C:\BOOST\INCLUDE\BOOST-1_33_1\BOOST目录。 2) 在Library files 中添加C:\BOOST\LIB目录。 11.测试
如果你不能确定,你的编译是否成功。就需要进行一下测试,拿正则表达式类为例。
测试如下程序
#include "stdafx.h"
#include <cstdlib> #include <stdlib.h> #include <boost/regex.hpp> #include <string> #include <iostream> using namespace std;
using namespace boost; regex expression("^select ([a-zA-Z]*) from ([a-zA-Z]*)");
int main(int argc, char* argv[])
{ std::string in; cmatch what; cout << "enter test string" << endl; getline(cin,in); if(regex_match(in.c_str(), what, expression)) { for(int i=0;i<what.size();i++) cout<<"str :"<<what[i].str()<<endl; } else { cout<<"Error Input"<<endl; } return 0; } 输入:select name from database;
输出:str:select name from table
str:name str:table 这样就完成了 单个库编译方法:(以regex为例)
编译boost.regex的另一种办法
1.运行vcvars32.bat,可以帮助设置好vc命令行环境 2.cd boost_1_33_1\libs\regex\build 3.nmake -vc6.mak 这种方式可以只编译regex 这时会在当前目录下生成vc6目录,里面有已编译好的lib和dll文件, 这样以后的步骤中可以设置regex库时指向这里, 包含文件需要设置到boost_1_33_1目录 另修正补充: 用bjam编译regex时,选项-sTOOLS=vc7中vc7改成vc71,否则下面最终生成工程时需要改个文件名( libboost_regex-vc7-mt-sgd-1_33_1.lib -> libboost_regex-vc71-mt-sgd-1_33_1.lib) 点评: 按照这个方法基本成功 编译库,大部分库编译成功,由于我主要是用boost.regex 组件 ,这个库是
成功得,测试通过,其它得库未测试,由于我编译得是1.34.0版本 文件得位置和此文说得不一样 ,build.bat 文件只需要修改一处 if "_%ProgramFiles%_" == "__" set ProgramFiles=F:\
设置正确得ProgramFiles变量。
设置变量的方法:cmd.exe set xxx=yyy
有点疑问的地方 yyy 是否要带引号 待以后解决? 18 juin 任意字节对齐的内存分配函数默认的编译器一般都是8字节对齐。所以需要在分配内存的时候,能按16或则其他字节对齐。
以下是从xvid工程中找到的任意字节对齐的内存分配函数。 17 juin gcc 中关键的几个选项CFLAGS 选项增加选项的数量,同时也增加编译的时间。所有的选项都会增加编译时间,有特别说明 "会增加编译时间" 的选项,表示会增加 "大量的" 编译时间 (跟其它选项比起来...)。 比较安全的选项首先是安全的选项:* 指令 o 参数与用法 [注二] o 说明 o 建议 * -O o -O (-O1), -O0, -O2, -O3, -Os o 依照后面数字的大小,针对效能最佳化的程度也不同 (稳定度也可能递减)。其中 -Os 是个比较特殊的等级,针对原始码大小最佳化。 o 可使用 -Os,降低程序加载的时间。 * -fforce-mem -fforce-addr o -fforce-mem, -fno-force-mem -fforce-addr, -fno-force-addr o 强制在运算前将内存中的数值 (mem) 或内存位置 (addr) 复制到缓存器中。启动这两个选项可以做出较好的程序代码。 o 这两个是好东西,启动它们!其中 -fforce-mem 已在 -O2, -O3, -Os 中启动,所以若您有用这三个选项的其中一个,只要 -fforce-addr 就够了。 * -fomit-frame-pointer o -fomit-frame-pointer, -fno-omit-frame-pointer o 若非必要,不将函式的 frame pointer 放进缓存器中。这将避免您的程序储存、设定、以及还原 frame pointer;也在许多函式中省下一个缓存器。这个选项可能让某些平台上的除错工作变成不可能!。若平台支持不使用 frame pointer 除错,这个选项将在 -O, -O2, -O3, -Os 中启动。 o 很抱歉,x86 刚好是非这个不可才能除错的平台之一。但是... 您想对您的桌面进行除错吗?若答案为非,您可以放心启动这个选项。 * -finline-functions o -finline-functions, -fno-inline-functions o 将所有简单的函式整合进呼叫他们的函式中。编译器会自动试探并决定那些函式值得被整合。于 -O3 时启动。 o 虽然这个选项会增加程序大小,但是他却是个增进效能的好东西。我建议您在这里启动它,然后使用下面一个指令指定 inline 条件。 * -finline-limit o -finline-limit=n o n 为决定函式是否能被 inline 的伪指令长度。预设的值为 600。 o 这个数值越小,程序启动的速度越快,但是运算的速度越慢。作为桌面使用,我建议 -finline-limit=400。 * -fmove-all-movables -freduce-all-givs o -fmove-all-movables, -fno-move-all-moveables -freduce-all-givs, -fno-redduse-all-givs o 这两个是循环最佳化技术,将无关循环内容的运算改在循环外执行。编译出的执行档可能更快也可能更慢,结果跟程序的写法有很大的关系。 o 虽然说效能跟程序写法有关,但是大部份的状况下这两个选项会做出比较小与比较快的程序代码,所以我建议您启动他们! * -freorder-blocks -freorder-functions o -freorder-blocks, -fno-reorder-blocks -freorder-functions, -fno-reorder-functions o 藉由重新编排程序区块来增进效能以及减少执行档大小。 o 这两个也是好东西,所以我建议您启动它们。缺点是会让编译时间变长。 * -fexpensive-optimizations o -fexpensive-optimizations, -fno-expensive-optimizations o 执行几个会加长编译时间的非主要最佳化程序。于 -O2, -O3, -Os 中预设开启。 o 虽然会增加编译时间,但是能增加效能也能减少执行档大小,所以建议启用。 * -falign-functions -falign-labels -falign-loops -falign-jumps o -falign-functions, -falign-functions=n -falign-labels, -falign-labels=n -falign-loops, -falign-loops=n -falign-jumps, -falign-jumps=n o 依照大于 n 的最小 2 的次方字节对齐函式 (functions)、标签 (labels)、循环 (loops)、跳跃 (jumps) 的起头,跳过至多 n 字节。 o 我知道这很抽象,解释起来要花很多篇幅,所以请各位使用默认值,亦即指定 -falign-functions, -falign-labels, -falign-loops, -falign-jumps,但是不指定 =n。 * -frename-registers o -frename-registers, -fno-rename-registers o 在作过缓存器定位之后,使用剩下来的缓存器。这个最佳化在有很多缓存器的 CPU 上最明显 (如 ARM、PowerPC... 等。x86 不属于他们的一份子)。会增加除错的困难度。 o 虽然在 x86 上不明显,但是还是有用。而且 x86-64 提供更多的缓存器,所以建议您还是应该打开它。 * -fweb o -fweb, -fno-web o 建立经常使用的缓存器网络。提供更佳的缓存器使用率。不过也会增加除错的困难度。 o 这个是安全选项中比较偏向实验性质的选项,虽然建议您启动,但是若启动之后程序不稳,请将它关闭。 于 -O3 时启动。 实验性质的选项以下是真的实验性质的东西,若启动之后系统不稳,请将他们关闭。 * 指令 平台相关选项最后是 x86 与 x86-64 相关的选项:* 指令 o 参数与用法 o 说明 o 建议 * -mcpu (已过期,可能在以后版本中移除。) -mtune -march o -mcpu=cpu-type -march=cpu-type -mtune=cpu-type o 依照不同的目标处理器进行最佳化。注意,若您指定了 -march,制作出的执行档将无法在其它 CPU 上使用。但是若光指定 -mtune,gcc 会避免使用平台专有指令集跟专用排程选项。可用的选项有: + i386:标准的 Intel i386 处理器 + i486:Intel 的 i486 处理器 (没有排程实作) + i586, pentium:没有 MMX 指令集的 Intel Pentium 处理器 + pentium-mmx:支持 MMX 指令集的 Intel PentiumMMX 处理器 + i686, pentiumpro:Intel PentiumPro 处理器 + pentium2:支持 MMX 指令集的 Intel Pentium2 处理器 + pentium3:支持 MMX 与 SSE 指令集的 Intel Pentium3 处理器 + pentium4:支持 MMX、SSE 与 SSE2 指令集的 Intel Pentium4 处理器 + k6:支持 MMX 指令集的 AMD K6 处理器 + k6-2, k6-3:支援 MMX 与 3DNow! 指令集的进阶版 AMD K6 处理器 + athlon, athlon-tbird:支援 MMX、 3DNow!、加强版 3DNow! 以及 SSE 预先加载指令集的 AMD Athlon 处理器 + athlon-4, athlon-xp, athlon-mp:支援 MMX、 3DNow!、加强版 3DNow! 以及完整 SSE 指令集的 AMD Athlon 处理器 + k8, opteron, athlon64, athlon-fx:支持 x86-64 指令集,以 AMD K8 核心为基础的处理器。(支援 MMX、SSE、SSE2、3DNow!、加强版 3DNow! 以及 64 位指令集。) + winchip-c6:IDT Winchip C6 处理器,以支持 MMX 指令集的 i486 处理。 + winchip2:IDT Winchip2 处理器,以支持 MMX 及 3DNow! 指令集的 i486 处理。 + c3:支援 MMX 及 3DNow! 指令集的 Via C3 处理器 (没有排程实作) + c3-2:支持 MMX 及 SSE 指令集的 Via C3 处理器 (没有排程实作) o 请依照您的系统指定 -march 与 -mtune,例如我的系统使用的是 "-march=athlon-xp -mtune=athlon-xp"。 * -mfpmath o -mfpmath=unit o 依照选择的单位制作执行文件。可用的单位有: + 387:使用标准的 387 浮点运算处理单元,为 i386 默认值。 + sse:使用 SSE 指令集提供的浮点运算处理指令,可以透过 -msse 或 -msse2 来启用。在 x86-64 平台上,这个选项是预设启用的。 + sse,387:使用标准 387 浮点运算处理单元与 SSE 指令集,这将提供将近一倍的额外缓存器,以及可能增加浮点运算处理效能。小心使用这个选项,因为这个技术还处于实验性质,可能造成系统不稳。 o 若您使用支持 SSE 的处理器,可以尝试使用比较快的 -mfpmath=sse,387。若您比较胆小 (怕当机),可以使用 -mfpmath=sse。 * -mmmx -msse -msse2 -msse3 -m3dnow o -mmmx, -mno-mmx -msse, -mno-sse -msse2, -mno-sse2 -msse3, -mno-sse3 -m3dnow, -mno-3dnow o 启动或关闭指令集支持。 o 请依照您的系统启动或关闭这些指令集支持。有关处理器支持的指令集,可透过 cat /proc/cpuinfo 来查询。 * -maccumulate-outgoing-args o -maccumulate-outgoing-args, -mno-accumulate-outgoing-args o 在函式起始时,计算输出参数所需的空间。在大部份现代处理器上,由于降低依存性、增进排程、以及在堆栈分界不等于 2 的时候降低堆栈使用率,这个选项可以增加一些效能。缺点是执行档会变大。 o 由于执行档会变大,所以不太建议使用。 * -malign-stringops o -malign-stringops, -mno-align-stringops o 决定是否将整合进原始码的目标字符串操作数对齐。这可以缩小执行档大小,以及在目标字符串操作数已经对齐时增加一些效能。 o 两面刃,所以请自己决定... * -minline-all-stringops o -minline-all-stringops, -mno-inline-all-stringops o 预设中 GCC 只将知道目的地会被对齐在 4bytes 界线的字符串操作数整合进程序代码。这个选项启动更多的整合,增加执行档大小,不过可能会增加需要快速 memcpy, strlen 以及 memset 的程序。 o 由于会增加程序代码大小,而又不是那么多程序会使用 memcpy/strlen/memset 等函式,所以建议不使用。 其它选项其它与最佳化无关的 CFLAGS:* -pipe o -pipe o 于程序间通讯时使用管线,而不是暂存盘。GNU 组译器支持此选项。 o 可以缩短一些编译时间,建议使用。 建议的 CFLAGS根据不同的用途,每个系统的 CFLAGS 也不尽相同。以下列出建议的 CFLAGS。其中请将 换成您的 CPU,以及根据系统支持程度启动 里面的选项: 请注意,这里列出的 CFLAGS 并不是最好的,也永远不会有最好的 CFLAGS。了解每个选项的用意与意义,组合最适合您的 CFLAGS 才是本章的要点,提供的 CFLAGS 只是作为参考用的。若您对这里列出的 CFLAGS 有任何意见,欢迎至 GOT 的讨论区 (http://forums.gentoo.org.tw/ ) 与大家讨论 Smile 注:可能您觉得 99.999 的 uptime 非常高,但其实这是服务器系统 uptime 的起跳数字。让我们算算,1 day = 86400 secs,1 year = 365 days,所以 1 year = 31536000 secs,套用 99.999% 的 uptime 以后,downtime 是 315.36 秒。也就是一年下线时间约五分钟。考虑到服务器开机比较慢 (有许多系统测试跟程序启动),这个数据是一年约下线 1~2 次。桌面系统的 99.99% 是这个数字的十倍,而桌面系统开机比较快,整理之后是约一星期重开一次。 注二:大部份参数前面若加上 `no',表示关闭该参数。如 -fforce-mem 开启 force-mem,-fno-force-mem 将 force-mem 关闭。 16 juin 开始→运行→输入的命令集锦...Nslookup-------IP地址侦测器
explorer-------打开资源管理器 logoff--------注销命令 tsshutdn-------60秒倒计时关机命令 lusrmgr.msc----- 本机用户和组 services.msc-----本地服务设置 oobe/msoobe /a----检查XP是否激活 notepad--------打开记事本 cleanmgr-------**整理 net start messenger----开始信使服务 net stop messenger-----停止信使服务 compmgmt.msc-----计算机管理 conf-----------启动 netmeeting dvdplay--------DVD播放器 charmap--------启动字符映射表 diskmgmt.msc----磁盘管理实用程序 calc-----------启动计算器 dfrg.msc-------磁盘碎片整理程序 chkdsk.exe-----Chkdsk磁盘检查 devmgmt.msc--- 设备管理器 regsvr32 /u *.dll----停止dll文件运行 drwtsn32------ 系统医生 rononce -p ----15秒关机 dxdiag---------检查DirectX信息 regedt32-------注册表编辑器 Msconfig.exe---系统配置实用程序 rsop.msc-------组策略结果集 mem.exe--------显示内存使用情况 regedit.exe----注册表 winchat--------XP自带局域网聊天 progman--------程序管理器 winmsd---------系统信息 perfmon.msc----计算机性能监测程序 winver---------检查Windows版本 sfc /scannow-----扫描错误并复原 taskmgr-----任务管理器(2000/xp/2003) wmimgmt.msc----打开windows管理体系结构(WMI) wupdmgr--------windows更新程序 w脚本--------windows脚本宿主设置 write----------写字板 winmsd---------系统信息 wiaacmgr-------扫描仪和照相机向导 mem.exe--------显示内存使用情况 Msconfig.exe---系统配置实用程序 mplayer2-------简易widnows media player mspaint--------画图板 mstsc----------远程桌面连接 mplayer2-------媒体播放机 magnify--------放大镜实用程序 mmc------------打开控制台 mobsync--------同步命令 dcomcnfg-------打开系统组件服务 ddeshare-------打开DDE共享设置 dvdplay--------DVD播放器 net stop messenger-----停止信使服务 net start messenger----开始信使服务 notepad--------打开记事本 nslookup-------网络管理的工具向导 ntbackup-------系统备份和还原 narrator-------屏幕"讲述人" ntmsmgr.msc----移动存储管理器 ntmsoprq.msc---移动存储管理员*作请求 netstat -an----(TC)命令检查接口 syncapp--------创建一个公文包 sysedit--------系统配置编辑器 sigverif-------文件签名验证程序 sndrec32-------录音机 shrpubw--------创建共享文件夹 secpol.msc-----本地安全策略 syskey---------系统加密,一旦加密就不能解开,保护windows xp系统的双重密码 services.msc---本地服务设置 Sndvol32-------音量控制程序 sfc.exe--------系统文件检查器 sfc /scannow---windows文件保护 tsshutdn-------60秒倒计时关机命令 tourstart------xp简介(安装完成后出现的漫游xp程序) taskmgr--------任务管理器 eventvwr-------事件查看器 eudcedit-------造字程序 explorer-------打开资源管理器 packager-------对象包装程序 perfmon.msc----计算机性能监测程序 progman--------程序管理器 regedit.exe----注册表 rsop.msc-------组策略结果集 regedt32-------注册表编辑器 rononce -p ----15秒关机 regsvr32 /u *.dll----停止dll文件运行 regsvr32 /u zipfldr.dll------取消ZIP支持 cmd.exe--------CMD命令提示符 chkdsk.exe-----Chkdsk磁盘检查 certmgr.msc----证书管理实用程序 calc-----------启动计算器 charmap--------启动字符映射表 cliconfg-------SQL SERVER 客户端网络实用程序 Clipbrd--------剪贴板查看器 conf-----------启动netmeeting cleanmgr-------**整理 ciadv.msc------索引服务程序 osk------------打开屏幕键盘 iexpress-------木马捆绑工具,系统自带 fsmgmt.msc-----共享文件夹管理器 utilman--------辅助工具管理器 gpedit.msc-----组策略 convert 盘符:/fs:ntfs-----不删除文档将磁盘转换成NTFS格式 2 juin GDB教程(一)摘自:http://www.cublog.cn/u/9861/showart_411310.html
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓"寸有所长,尺有所短"就是这个道理。 一般来说,GDB主要帮忙你完成下面四个方面的功能: 1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) 3、当程序被停住时,可以检查此时你的程序中所发生的事。 4、动态的改变你程序的执行环境。 从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。 一个调试示例
—————— 源程序:tst.c 1 #include <stdio.h> 2 3 int func(int n) 4 { 5 int sum=0,i; 6 for(i=0; i<n; i++) 7 { 8 sum+=i; 9 } 10 return sum; 11 } 12 13 14 main() 15 { 16 int i; 17 long result = 0; 18 for(i=1; i<=100; i++) 19 { 20 result += i; 21 } 22 23 printf("result[1-100] = %d \n", result ); 24 printf("result[1-250] = %d \n", func(250) ); 25 } 编译生成执行文件:(Linux下) hchen/test> cc -g tst.c -o tst 使用GDB调试: hchen/test> gdb tst <---------- 启动GDB GNU gdb 5.1.1 Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-suse-linux"... (gdb) l <-------------------- l命令相当于list,从第一行开始例出原码。 1 #include <stdio.h> 2 3 int func(int n) 4 { 5 int sum=0,i; 6 for(i=0; i<n; i++) 7 { 8 sum+=i; 9 } 10 return sum; (gdb) <-------------------- 直接回车表示,重复上一次命令 11 } 12 13 14 main() 15 { 16 int i; 17 long result = 0; 18 for(i=1; i<=100; i++) 19 { 20 result += i; (gdb) break 16 <-------------------- 设置断点,在源程序第16行处。 Breakpoint 1 at 0x8048496: file tst.c, line 16. (gdb) break func <-------------------- 设置断点,在函数func()入口处。 Breakpoint 2 at 0x8048456: file tst.c, line 5. (gdb) info break <-------------------- 查看断点信息。 Num Type Disp Enb Address What 1 breakpoint keep y 0x08048496 in main at tst.c:16 2 breakpoint keep y 0x08048456 in func at tst.c:5 (gdb) r <--------------------- 运行程序,run命令简写 Starting program: /home/hchen/test/tst Breakpoint 1, main () at tst.c:17 <---------- 在断点处停住。 17 long result = 0; (gdb) n <--------------------- 单条语句执行,next命令简写。 18 for(i=1; i<=100; i++) (gdb) n 20 result += i; (gdb) n 18 for(i=1; i<=100; i++) (gdb) n 20 result += i; (gdb) c <--------------------- 继续运行程序,continue命令简写。 Continuing. result[1-100] = 5050 <----------程序输出。 Breakpoint 2, func (n=250) at tst.c:5 5 int sum=0,i; (gdb) n 6 for(i=1; i<=n; i++) (gdb) p i <--------------------- 打印变量i的值,print命令简写。 $1 = 134513808 (gdb) n 8 sum+=i; (gdb) n 6 for(i=1; i<=n; i++) (gdb) p sum $2 = 1 (gdb) n 8 sum+=i; (gdb) p i $3 = 2 (gdb) n 6 for(i=1; i<=n; i++) (gdb) p sum $4 = 3 (gdb) bt <--------------------- 查看函数堆栈。 #0 func (n=250) at tst.c:5 #1 0x080484e4 in main () at tst.c:24 #2 0x400409ed in __libc_start_main () from /lib/libc.so.6 (gdb) finish <--------------------- 退出函数。 Run till exit from #0 func (n=250) at tst.c:5 0x080484e4 in main () at tst.c:24 24 printf("result[1-250] = %d \n", func(250) ); Value returned is $6 = 31375 (gdb) c <--------------------- 继续运行。 Continuing. result[1-250] = 31375 <----------程序输出。 Program exited with code 027. <--------程序退出,调试结束。 (gdb) q <--------------------- 退出gdb。 hchen/test> 好了,有了以上的感性认识,还是让我们来系统地认识一下gdb吧。 使用GDB
———— 一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如: > cc -g hello.c -o hello > g++ -g hello.cpp -o hello 如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用gdb来调试他。 启动GDB的方法有以下几种: 1、gdb <program> program也就是你的执行文件,一般在当然目录下。 2、gdb <program> core 用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。 3、gdb <program> <PID> 如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。 GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb -help查看。我在下面只例举一些比较常用的参数: -symbols <file> -s <file> 从指定文件中读取符号表。 -se file 从指定文件中读取符号表信息,并把他用在可执行文件中。 -core <file> -c <file> 调试时core dump的core文件。 -directory <directory> -d <directory> 加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。 GDB的命令概貌 ——————— 启动gdb后,就你被带入gdb的调试环境中,就可以使用gdb的命令开始调试程序了,gdb的命令可以使用help命令来查看,如下所示: /home/hchen> gdb GNU gdb 5.1.1 Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-suse-linux". (gdb) help List of classes of commands: aliases -- Aliases of other commands breakpoints -- Making program stop at certain points data -- Examining data files -- Specifying and examining files internals -- Maintenance commands obscure -- Obscure features running -- Running the program stack -- Examining the stack status -- Status inquiries support -- Support facilities tracepoints -- Tracing of program execution without stopping the program user-defined -- User-defined commands Type "help" followed by a class name for a list of commands in that class. Type "help" followed by command name for full documentation. Command name abbreviations are allowed if unambiguous. (gdb) gdb的命令很多,gdb把之分成许多个种类。help命令只是例出gdb的命令种类,如果要看种类中的命令,可以使用help <class> 命令,如:help breakpoints,查看设置断点的所有命令。也可以直接help <command>来查看命令的帮助。 gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,命令的前几个字符应该要标志着一个唯一的命令,在Linux下,你可以敲击两次TAB键来补齐命令的全称,如果有重复的,那么gdb会把其例出来。
示例一:在进入函数func时,设置一个断点。可以敲入break func,或是直接就是b func (gdb) b func Breakpoint 1 at 0x8048458: file hello.c, line 10. 示例二:敲入b按两次TAB键,你会看到所有b打头的命令: (gdb) b backtrace break bt (gdb) 示例三:只记得函数的前缀,可以这样: (gdb) b make_ <按TAB键> (再按下一次TAB键,你会看到:) make_a_section_from_file make_environ make_abs_section make_function_type make_blockvector make_pointer_type make_cleanup make_reference_type make_command make_symbol_completion_list (gdb) b make_ GDB把所有make开头的函数全部例出来给你查看。 示例四:调试C++的程序时,有可以函数名一样。如: (gdb) b 'bubble( M-? bubble(double,double) bubble(int,int) (gdb) b 'bubble( 你可以查看到C++中的所有的重载函数及参数。(注:M-?和"按两次TAB键"是一个意思) 要退出gdb时,只用发quit或命令简称q就行了。 GDB中运行UNIX的shell程序 ———————————— 在gdb环境中,你可以执行UNIX的shell的命令,使用gdb的shell命令来完成: shell <command string> 调用UNIX的shell来执行<command string>,环境变量SHELL中定义的UNIX的shell将会被用来执行<command string>,如果SHELL没有定义,那就使用UNIX的标准shell:/bin/sh。(在Windows中使用Command.com或cmd.exe) 还有一个gdb命令是make: make <make-args> 可以在gdb中执行make命令来重新build自己的程序。这个命令等价于"shell make <make-args>"。 在GDB中运行程序
———————— 当以gdb <program>方式启动gdb后,gdb会在PATH路径和当前目录中搜索<program>的源文件。如要确认gdb是否读到源文件,可使用l或list命令,看看gdb是否能列出源代码。 在gdb中,运行程序使用r或是run命令。程序的运行,你有可能需要设置下面四方面的事。 1、程序运行参数。 set args 可指定运行时参数。(如:set args 10 20 30 40 50) show args 命令可以查看设置好的运行参数。 2、运行环境。 path <dir> 可设定程序的运行路径。 show paths 查看程序的运行路径。 set environment varname [=value] 设置环境变量。如:set env USER=hchen show environment [varname] 查看环境变量。 3、工作目录。 cd <dir> 相当于shell的cd命令。 pwd 显示当前的所在目录。 4、程序的输入输出。 info terminal 显示你程序用到的终端的模式。 使用重定向控制程序输出。如:run > outfile tty命令可以指写输入输出的终端设备。如:tty /dev/ttyb 调试已运行的程序
———————— 两种方法: 1、在UNIX下用ps查看正在运行的程序的PID(进程ID),然后用gdb <program> PID格式挂接正在运行的程序。 2、先用gdb <program>关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程的PID。并用detach来取消挂接的进程。 暂停 / 恢复程序运行 ————————— 调试程序中,暂停程序运行是必须的,GDB可以方便地暂停程序的运行。你可以设置程序的在哪行停住,在什么条件下停住,在收到什么信号时停往等等。以便于你查看运行时的变量,以及运行时的流程。 当进程被gdb停住时,你可以使用info program 来查看程序的是否在运行,进程号,被暂停的原因。 在gdb中,我们可以有以下几种暂停方式:断点(BreakPoint)、观察点(WatchPoint)、捕捉点(CatchPoint)、信号(Signals)、线程停止(Thread Stops)。如果要恢复程序运行,可以使用c或是continue命令。 一、设置断点(BreakPoint)
我们用break命令来设置断点。正面有几点设置断点的方法: break <function> 在进入指定函数时停住。C++中可以使用class::function或function(type,type)格式来指定函数名。 break <linenum> 在指定行号停住。 break +offset break -offset 在当前行号的前面或后面的offset行停住。offiset为自然数。 break filename:linenum 在源文件filename的linenum行处停住。 break filename:function 在源文件filename的function函数的入口处停住。 break *address 在程序运行的内存地址处停住。 break break命令没有参数时,表示在下一条指令处停住。 break ... if <condition> ...可以是上述的参数,condition表示条件,在条件成立时停住。比如在循环境体中,可以设置break if i=100,表示当i为100时停住程序。 查看断点时,可使用info命令,如下所示:(注:n表示断点号) info breakpoints [n] info break [n] 二、设置观察点(WatchPoint) 观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点: watch <expr> 为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时,停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时,停住程序。 info watchpoints 列出当前所设置了的所有观察点。 三、设置捕捉点(CatchPoint) 你可设置捕捉点来补捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C++的异常。设置捕捉点的格式为: catch <event> 当event发生时,停住程序。event可以是下面的内容: 1、throw 一个C++抛出的异常。(throw为关键字) 2、catch 一个C++捕捉到的异常。(catch为关键字) 3、exec 调用系统调用exec时。(exec为关键字,目前此功能只在HP-UX下有用) 4、fork 调用系统调用fork时。(fork为关键字,目前此功能只在HP-UX下有用) 5、vfork 调用系统调用vfork时。(vfork为关键字,目前此功能只在HP-UX下有用) 6、load 或 load <libname> 载入共享库(动态链接库)时。(load为关键字,目前此功能只在HP-UX下有用) 7、unload 或 unload <libname> 卸载共享库(动态链接库)时。(unload为关键字,目前此功能只在HP-UX下有用) tcatch <event> 只设置一次捕捉点,当程序停住以后,应点被自动删除。 GDB教程(四)七、设置显示选项 GDB中关于显示的选项比较多,这里我只例举大多数常用的选项。 set print address
show print address set print elements <number-of-elements> $1 = { set print pretty off 当打开这个开关时,执行 p foo 命令后,会如下显示: show print union 当你用GDB的print查看程序运行时的数据时,你每一个print都会被GDB记录下来。GDB会以$1, $2, $3 .....这样的方式为你每一个print命令编上号。于是,你可以使用这个编号访问以前的表达式,如$1。这个功能所带来的好处是,如果你先前输入了一个比较长的表达式,如果你还想查看这个表达式的值,你可以使用历史记录来访问,省去了重复输入。 你可以在GDB的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。要定义一个GDB的变量很简单只需。使用GDB的set命令。GDB的环境变量和UNIX一样,也是以$起头。如: 要查看寄存器的值,很简单,可以使用如下命令: 一旦使用GDB挂上被调试程序,当程序运行起来后,你可以根据自己的调试思路来动态地在GDB中更改当前被调试程序的运行线路或是其变量的值,这个强大的功能能够让你更好的调试你的程序,比如,你可以在程序的一次运行中走遍程序的所有分支。 修改被调试程序运行时的变量值,在GDB中很容易实现,使用GDB的print命令即可完成。如: 因为,set width是GDB的命令,所以,出现了"Invalid syntax in expression"的设置错误,此时,你可以使用set var命令来告诉GDB,width不是你GDB的参数,而是程序的变量名,如: 二、跳转执行 一般来说,被调试程序会按照程序代码的运行顺序依次执行。GDB提供了乱序执行的功能,也就是说,GDB可以修改程序的执行顺序,可以让程序执行随意跳跃。这个功能可以由GDB的jump命令来完:
使用singal命令,可以产生一个信号量给被调试的程序。如:中断信号Ctrl+C。这非常方便于程序的调试,可以在程序运行的任意位置设置断点,并在该断点用GDB产生一个信号量,这种精确地在某处产生信号非常有利程序的调试。 四、强制函数返回 如果你的调试断点在某个函数中,并还有语句没有执行完。你可以使用return命令强制函数忽略还没有执行的语句并返回。 call <expr>
在不同语言中使用GDB GDB支持下列语言:C, C++, Fortran, PASCAL, Java, Chill, assembly, 和 Modula-2。一般说来,GDB会根据你所调试的程序来确定当然的调试语言,比如:发现文件名后缀为".c"的,GDB会认为是C程序。文件名后缀为".C, .cc, .cp, .cpp, .cxx, .c++"的,GDB会认为是C++程序。而后缀是".f, .F"的,GDB会认为是Fortran程序,还有,后缀为如果是".s, .S"的会认为是汇编语言。 也就是说,GDB会根据你所调试的程序的语言,来设置自己的语言环境,并让GDB的命令跟着语言环境的改变而改变。比如一些GDB命令需要用到表达式或变量时,这些表达式或变量的语法,完全是根据当前的语言环境而改变的。例如C/C++中对指针的语法是*p,而在Modula-2中则是p^。并且,如果你当前的程序是由几种不同语言一同编译成的,那到在调试过程中,GDB也能根据不同的语言自动地切换语言环境。这种跟着语言环境而改变的功能,真是体贴开发人员的一种设计。
show language 当set language命令后什么也不跟的话,你可以查看GDB所支持的语言种类: GDB教程(三)查看源程序 一、显示源代码 GDB 可以打印出所调试程序的源代码,当然,在程序编译时一定要加上-g的参数,把源程序信息编译到执行文件中。不然就看不到源程序了。当程序停下来以后,GDB会报告程序停在了那个文件的第几行上。你可以用list命令来打印程序的源代码。还是来看一看查看源代码的GDB命令吧。 一般是打印当前行的上5行和下5行,如果显示函数是是上2行下8行,默认是10行,当然,你也可以定制显示的范围,使用下面命令可以设置一次显示源程序的行数。 set listsize <count> list命令还有下面的用法: list <first>, <last> 一般来说在list后面可以跟以下这们的参数: <linenum> 行号。 二、搜索源代码 不仅如此,GDB还提供了源代码搜索的命令: forward-search <regexp> reverse-search <regexp>
某些时候,用-g编译过后的执行程序中只是包括了源文件的名字,没有路径名。GDB提供了可以让你指定源文件的路径的命令,以便GDB进行搜索。 directory <dirname ... > 四、源代码的内存 你可以使用info line命令来查看源代码在内存中的地址。info line后面可以跟"行号","函数名","文件名:行号","文件名:函数名",这个命令会打印出所指定的源码在运行时的内存地址,如: (gdb) info line tst.c:func 还有一个命令(disassemble)你可以查看源程序的当前执行时的机器码,这个命令会把目前内存中的指令dump出来。如下面的示例表示查看函数func的汇编代码。 (gdb) disassemble func 查看运行时数据 print和许多GDB的命令一样,可以接受一个表达式,GDB会根据当前的程序运行的数据来计算这个表达式,既然是表达式,那么就可以是当前程序运行中的const常量、变量、函数等内容。可惜的是GDB不能使用你在程序中所定义的宏。 在GDB中,你可以随时查看以下三种变量的值: 三、数组 有时候,你需要查看一段连续的内存空间的值。比如数组的一段,或是动态分配的数据的大小。你可以使用GDB的"@"操作符,"@"的左边是第一个内存的地址的值,"@"的右边则你你想查看内存的长度。例如,你的程序中有这样的语句: p *array@len @的左边是数组的首地址的值,也就是变量array所指向的内容,右边则是数据的长度,其保存在变量len中,其输出结果,大约是下面这个样子的: 如果是静态数组的话,可以直接用print数组名,就可以显示数组中所有数据的内容了。 一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显示格式: (gdb) p i
你可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示: n/f/u三个参数可以一起使用。例如: 你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的GDB命令是display。 GDB教程(二)四、维护停止点 上面说了如何设置程序的停止点,GDB中的停止点也就是上述的三类。在GDB中,如果你觉得已定义好的停止点没有用了,你可以使用delete、clear、disable、enable这几个命令来进行维护。 clear clear <function> clear <linenum> delete [breakpoints] [range...] disable [breakpoints] [range...] enable [breakpoints] [range...] enable [breakpoints] once range... enable [breakpoints] delete range... 五、停止条件维护 前面在说到设置断点时,我们提到过可以设置一个条件,当条件成立时,程序自动停止,这是一个非常强大的功能,这里,我想专门说说这个条件的相关维护命令。一般来说,为断点设置一个条件,我们使用if关键词,后面跟其断点条件。并且,条件设置好后,我们可以用condition命令来修改断点的条件。(只有break和watch命令支持if,catch目前暂不支持if) condition <bnum> <expression> condition <bnum>
ignore <bnum> <count> 六、为停止点设定运行命令 我们可以使用GDB提供的command命令来设置停止点的运行命令。也就是说,当运行的程序在被停止住时,我们可以让其自动运行一些别的命令,这很有利行自动化调试。对基于GDB的自动化调试是一个强大的支持。
为断点号bnum指写一个命令列表。当程序被该断点停住时,gdb会依次运行命令列表中的命令。 例如: break foo if x>0 如果你要清除断点上的命令序列,那么只要简单的执行一下commands命令,并直接在打个end就行了。 在C++中,可能会重复出现同一个名字的函数若干次(函数重载),在这种情况下,break <function>不能告诉GDB要停在哪个函数的入口。当然,你可以使用break <function(type)>也就是把函数的参数类型告诉GDB,以指定一个函数。否则的话,GDB会给你列出一个断点菜单供你选择你所需要的断点。你只要输入你菜单列表中的编号就可以了。如: (gdb) b String::after 可见,GDB列出了所有after的重载函数,你可以选一下列表编号就行了。0表示放弃设置断点,1表示所有函数都设置断点。 当程序被停住了,你可以用continue命令恢复程序的运行直到程序结束,或下一个断点到来。也可以使用step或next命令单步跟踪程序。 continue [ignore-count]
next <count> set step-mode set step-mod off finish until 或 u stepi 或 si 信号是一种软中断,是一种处理异步事件的方法。一般来说,操作系统都支持许多信号。尤其是UNIX,比较重要应用程序一般都会处理信号。UNIX定义了许多信号,比如SIGINT表示中断字符信号,也就是Ctrl+C的信号,SIGBUS表示硬件故障的信号;SIGCHLD表示子进程状态改变信号;SIGKILL表示终止程序运行的信号,等等。信号量编程是UNIX下非常重要的一种技术。 GDB有能力在你调试程序的时候处理任何一种信号,你可以告诉GDB需要处理哪一种信号。你可以要求GDB收到你所指定的信号时,马上停住正在运行的程序,以供你进行调试。你可以用GDB的handle命令来完成这一功能。 handle <signal> <keywords...> nostop
如果你程序是多线程的话,你可以定义你的断点是否在所有的线程上,或是在某个特定的线程。GDB很容易帮你完成这一工作。 break <linespec> thread <threadno> 当你的程序被GDB停住时,所有的运行线程都会被停住。这方便你你查看运行程序的总体情况。而在你恢复程序运行时,所有的线程也会被恢复运行。那怕是主进程在被单步调试时。 当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入"栈"(Stack)中。你可以用GDB命令来查看当前的栈中的信息。 下面是一些查看函数调用栈信息的GDB命令: backtrace backtrace <-n> frame <n> 上面的命令,都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命令: |
|
|