main.c/main.cpp
#include
int main(int argc, char *argv[])
{
printf("Hello world!\n");
return 0;
}
gcc -o hello main.c
./hello
g++ -o hello main.cpp
./hello
main.c->main.obj(lib文件)->hello
gcc/g++ 编译选项
gcc -o -O3 Wall hello main.c -l/homelzyrinc/ -L/home/zyr/ibs/ -lmath /home/zyr/ibs/ibmath.so
gcc- > .c,g++> .cpp
-o outile输出到指定的文件
-E 仅作预处理(code.i,不进行编译、汇编和链接。)
-S 仅编译到汇编语言(code.s),不进行汇编和链接。
-c 编译、汇编到目标代码(code.o),不进行链接含
-shared 生成共享目标文件。通常用在建立共享库时。我”
-static 禁止使用共享连接的
-llibrary 进行链接时搜索名为library的库-ldir把dir加入到搜索头文件的路径列表中。
-Ldir 把dir加入到搜索库文件的路径列表中。
例子: $ gcc -I/home/foo -L/home/foo -Itest test.c -o test
-Dname 预定义一个名为name的宏,
例子: $ gcc -DTEST_ CONFIG test.c -o test
-Dname =definition 预定义名为name,值为definition的宏。
-ggdb -ggdblevel
为调试器gdb生成调试信息。level 可以为1,2,3,默认值为2
-g -glevel
生成操作系统本地格式的调试信息。-g和-ggdb并不太相同,-g会生成gdb之外的信息。level取值同上。
-Wall 会打开-一些很有用的警告选项,建议编译时加此选项。
-w 禁止显示所有警告信息。
Optimization
-O0 禁正编译器进行优化。默认为此项。
-O -O1 尝试优化编译时间和可执行文件大小。
-O2 更多的优化,会尝试几乎全部的优化功能,但不会进行“空间换时间”的优化方法。
-O3 在-O2的基础上再打开一些优化选项:-finline-functions, -funswitch-loops 和-fgcse-after-reload。
-Os 对生成文件大小进行优化。它会打开-O2开的全部选项,除了会那些增加文伴大小的。
Makefile的编写
hello:main.o
g++ -o hello main.o
main.o:main.cpp
g++ -c main.cpp -o main.o
clean:
rm -f *.o hello
注意:代码第2,4, 6行都是以一个tab字符
了解Scons :跨平台的gnu make替代工具分其集成功能类似
autoconf/automake scons是一一个更简便,更可靠,更高效的编译软件。
Scons help doc :http://blog.sina.Com.cn/s/blog 5eb8ebcb0100sjlb.html
http://www.ibm.com/ developerworks/cn/linux/l-cn-sconsl
使用示例
func.h
#ifndef _FUNC_H_
#define _FUNC_H_
#include
void my_print();
#endif
func.cpp
#include "func.h"
void my_print()
{
printf("Hello world!\n");
return;
}
main.cpp
#include "func.h"
int main(int argc,char *argv[])
{
int i = 10;
my_print();
printf("i=%d\n", i);
return 0;
}
Makefile编写
hello:main.o func.o
g++ -g -o hello main.o func.o
func.o:func.cpp
g++ -g -c func.cpp -o func.o
main.o:main.cpp
g++ -g -c main.cpp -o main.o
clean:
rm -f main *.o
==================
Makefile的规则
目标:需要的条件(依赖)
命令(注意前面用tab键开头)
解释:
1目标可以是一个或多个,可以是Object File, 也可以是执行文件,甚至可以是一个标签。
2需要的条件就是生成目标所需要的文件或目标
3命令就是生成目标所需要执行的脚本,比如gcc,g++,rm等
上面的Makefile.针对的是一个源文件。那么假如一一个程 序项目里有多个源文件,应该怎么写Makefile呢?
Makefile
ovempass:main.o http.o httppost.o
g++ -g -o overpass :main.o http.o httppost.o -L. -lhiredis -lpthread
main.o:main.cpp
g++ -g -o main.cpp -o main.o
http.o:http.cpp
g++ -g -c http.cpp -o http.o
httpost.o:httppost.cpp
g++ -g -c httppost.cpp -o httppost.o
clean:
rm -f *.o overpass
其中,第2,4,6,8,10 行后面都是一个tab字符,这一点要特别注意,否则在执行make的时候,GCC会报错。
make -f 指定makefile名
Makefile的变量
OBJS = file1. o file2.o
CC = gcc
CFLAGS = -Wall -O -g
INC = /root/includes/
LIBS= /root/libs/
helloworld : $(OBJS)
$(CC) $(OBJS) -o helloworld
file1.o: file1.c
$(CC) $(CFLAGS) -C -I$(INC) file1.c -o file1.o -L$(LIBS) -lmath
file2.o : file2.c
$(CC) $(CFLAGS) -c -I$(INC) file2.c -o file2.o -L$(LIBS)-Imath
clean:
rm -rf' *o helloworld
.c.o规则
hello:file1.o file2.o
gcc -o hello file1.o file2.o
file1.o:file1.c
gcc -c file1.c -o file1.o
file2.o:file2.c
gcc -c file2.c -o file2.o
clean:
rm -f *.o hello
.c.o规则表示所有的.o文件都是依赖与相应的c文件的(暂时无法加上调试信息-g和-|等标志)
hello:file1.o fiel2.o
gcc -o $@ $^
.C.O:
gcc -c $< -o $@
clean:
rm -f *o hello
image.png
Makefile .c.o
OBJS = file1.o file2. o
CC = gcc
CFLAGS = -Wall -O -g
INC= /root/includes/
LIBS = /root/libs/
helloworld : $(OBJS)
$(CC) -o $@ $^
.c.o:
$(CC) $(CFLAGS) -c -I$(INC)$< -o $@ -L$(LIBS) -lmath
clean:
rm -rf *.o helloworld
GDB 调试命令
gdb hello
List
b-break for func,line
r-run
c-continue
s-step, into
n-step over
p-print
q-quit
多线程:
gdb -p pid .
set scheduler-locking on
info threads
thread2
b functionname
c/s/n
objdump S hello//查看汇编代码
1简介
GDB(GNU Debugger)是GCC的调试工具。其功能强大,现描述如下:
GDB主要帮忙你完成下面四个方面的功能:
1.启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2.可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3.当程序被停住时,可以检查此时你的程序中所发生的事。
4.动态的改变你程序的执行环境。
2 生成调试信息
一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如:
gcc -g hello.c -o hello
g++ -g hello.cpp -o hello
如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用gdb来调试他。
3 启动GDB的方法
gdb program
program 也就是你的执行文件,一般在当前目录下。
4 程序运行上下文
4.1 程序运行参数
set args 可指定运行时参数。(如:set args 10 20 30 40 50 )
show args 命令可以查看设置好的运行参数。
run 启动程序
4.2 工作目录
cd 相当于shell的cd命令。
pwd 显示当前的所在目录。
5 设置断点
5.1 简单断点
break 设置断点,可以简写为b
b 10 设置断点,在源程序第10行
b func 设置断点,在func函数入口处
5.2 多文件设置断点
在进入指定函数时停住:
C++中可以使用class::function或function(type,type)格式来指定函数名。如果有名称空间,可以使用namespace::class::function或者function(type,type)格式来指定函数名。
break filename:linenum -- 在源文件filename的linenum行处停住
break filename:function -- 在源文件filename的function函数的入口处停住
break class::function或function(type,type) -- 在类class的function函数的入口处停住
break namespace::class::function -- 在名称空间为namespace的类class的function函数的入口处停住
5.3 查询所有断点
info b
6条件断点
一般来说,为断点设置一个条件,我们使用if关键词,后面跟其断点条件。
设置一个条件断点
b test.c:8 if intValue == 5
7 维护停止点
delete [range...] 删除指定的断点,如果不指定断点号,则表示删除所有的断点。range 表示断点号的范围(如:3-7)。其简写命令为d。
比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,就好像回收站一样。
disable [range...]
disable所指定的停止点,如果什么都不指定,表示disable所有的停止点。简写命令是dis.
enable [range...]
enable所指定的停止点,如果什么都不指定,表示enable所有的停止点。简写命令是ena.
8 调试代码
run 运行程序,可简写为r
next 单步跟踪,函数调用当作一条简单语句执行,可简写为n
step 单步跟踪,函数调进入被调用函数体内,可简写为s
finish 退出进入的函数
until 在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体,可简写为u。
continue 继续运行程序,可简写为c
9 查看运行时数据
print 打印变量、字符串、表达式等的值,可简写为p
p count 打印count的值
10 自动显示
你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的GDB命令是display。
display 变量名
info display -- 查看display设置的自动显示的信息。
undisplay num(info display时显示的编号)
delete display dnums… -- 删除自动显示,dnums意为所设置好了的自动显式的编号。如果要同时删除几个,编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如:2-5)
disable display dnums…
enable display dnums…
disable和enalbe不删除自动显示的设置,而只是让其失效和恢复。
11查看修改变量的值
(gdb) ptype width -- 查看变量width的类型
type = double
(gdb) p width -- 打印变量width 的值
$4 = 13
你可以使用set var命令来告诉GDB,width不是你GDB的参数,而是程序的变量名,如:
(gdb) set var width=47
在你改变程序变量取值时,最好都使用set var格式的GDB命令。
12 显示源代码
GDB 可以打印出所调试程序的源代码,当然,在程序编译时一定要加上 –g 的参数,把源程序信息编译到执行文件中。不然就看不到源程序了。当程序停下来以后,
GDB会报告程序停在了那个文件的第几行上。你可以用list命令来打印程序的源代码。默认打印10行,还是来看一看查看源代码的GDB命令吧。
list linenum
Print lines centered around line number linenum in the current source file.
list function
显示函数名为function的函数的源程序。
list
显示当前行后面的源程序。
list -
显示当前行前面的源程序。
一般是打印当前行的上5行和下5行,如果显示函数是是上2行下8行,默认是10行,当然,你也可以定制显示的范围,使用下面命令可以设置一次显示源程序的行数。
set listsize count
设置一次显示源代码的行数。(unless the list argument explicitly specifies some other number)
show listsize
查看当前listsize的设置。
core文件调试
生成CORE文件并调试CORE文件:
查看系统CORE文件设置:ulimit -a
打开CORE文件: ulimit -c unlimited 或者 ulimit -c 1000
禁用: ulimit -c 0
调试CORE文件:
gdb programbin corefile
where/bt
如果持久打开CORE,需要设置
/etc/profiles 中的:
No core files by default
ulimit -c unlimited
ulimit -S -c 0 > /dev/nuI 2>&1
使之生效:
source /etc/profile
linux下可以使用eclipse或Code::Blocks等工具编写c/c++程序
静态库的编写
firstlib.h
/*firstlib.h*/
void Print();
firstlib.c
/*firstlib.c*/
#include
#include "firstlib.h"
void Print()
{
printf("hello first static lib\n");
}
Makefile:
libfirstlib.a:firstlib.c
gcc -c firstlib.c
ar -rsv libfirstlib.a firstlib.o
clean:
rm -f *.o *.a
静态库的使用
firstlib.h
/*firstlib.h*/
void Print();
main.c
#include "firstlib.h"
void main(void)
{
Print();
}
Makefile:
testlib:main.o
gcc -o testlib main.c -L. -lfirstlib
clean:
rm -f *.o testlib
动态库的编写
firstlib.h
/*firstlib.h*/
void Print();
firstlib.c
/*firstlib.c*/
#include
#include "firstlib.h"
void Print()
{
printf("hello first so lib\n");
}
Makefile:
libfirstlib.so:firstlib.c
gcc -shared -fPIC -o libfirstlib.so firstlib.c
clean:
rm -f *.so *.o
动态库的使用
firstlib.h
/*firstlib.h*/
void Print();
main.c
#include "firstlib.h"
void main(void)
{
Print();
}
Makefile:
main:main.c
gcc -o main -I. main.c -L. -lfirstlib
clean:
rm -f main *.o
注意:
将动态库拷贝到/lib或/usr/lib或/usr/lib64/中去如: sudo cp libfirstlib.so usr/ib64
linux中查看程序使用了哪些动态库:
ldd helloworld.
objdump -tT xxx.so 查看xxx.so的符号表
nm -D xxx.so 列出动态库的符号清单