GCC入门(上)
一、通过gcc --help了解hello.c的整个编译过程。
二、-Wall选项的作用
三、
//main.c
main()
{
hello(“bluze!\n”);
return 0;
}
//hello.h
#ifndef_HELLO_H_
#define_HELLO_H_
voidhello(const char* s);
#endif
//hello.c
#inlcude<stdio.h>
#include “hello.c”
voidhello(const char* s)
{
printf(“hello %s”,s);
}
gcc –Wallmain.c hello.c –o main
./main
等价于:
gcc –Wall–c hello.c –o hello.o
gcc –Wall–c main.c –o main.o
gcc –Wallmain.o hello.o –o main
./main
单独编译的好处是,如果修改了一个文件,只需重新编译改变的那个,对于大型程序可以节约时间。
GCC入门(下)
一、静态库(.a)与动态库(.so)的区别
二、ar rcs libhello.a hello.o //rcs 是replace and create 的意思
gcc –Wall main.clibhello.a –o main
或者 gcc –Wall main.c –o main –lhello
三、配置家目录下的~/.bash_profile文件进行环境变量的配置
(如export LIBRARY_PATH=”/root/cprograming/gcc_demo”),程序先在用户配置的环境变量中搜索相关库的路径,如果找不到就在系统路径下搜索相关项,如果再找不到,就报错!
从左至右搜索-I,-L路径。
三、生成动态库
gcc –shared–fPIC hello.o –o libhello.so
gcc –Wall–L. main.o –o main –libhello
四、运行共享库
1、 拷贝.so文件到系统共享库路径下,一般指/usr/lib
2、 更改LD_LIBRARY_PATH
3、 ldconfig,配置/etc/ld.so.conf,ldconfig更新ld.so.cache
Makefile(上)
一、
touchmain.c add.c add.h sub.c sub.h
//main.c
intmain()
{
return 0;
}
//Makefile
.PHONY:clean #显示指定clean为伪目标
main:main.oadd.o sub.o
gcc –Wall –g main.o add.o sub.o –o main
main.o:main.c
gcc –Wall –g –c main.c –o main.o
add.o:add.cadd.h
gcc –Wall –g –c add.c –o add.o
sub.o:sub.csub.h
gcc –Wall –g –c sub.c –o sub.o
clean:
rm –f main main.o add.o sub.o
$ make //默认情况下生成第一个目标
$makeclean //执行伪目标
$makeadd.o //可以单独生成某一个目标
二、
.PHONY:clean #显示指定clean为伪目标
OBJECTS=main.o add.o sub.o
main:$(OBJECTS)
gcc –Wall –g $^ –o $@
main.o:main.c
gcc –Wall –g –c $< –o $@
add.o:add.cadd.h
gcc –Wall –g –c $< –o $@
sub.o:sub.csub.h
gcc –Wall –g –c @< –o $@
clean:
@echo “delete…” #在前面加@表示不打印这句话本身,但打印delete...
rm –f main $(OBJECTS)
$@ 规则的目标文件
$< 规则的第一个依赖文件
$^ 规则的所有依赖文件
三、
$ touch01test.c 02test.c
//01test.c
intmain()
{
return 0;
}
//02test.c
intmain()
{
return 0;
}
#Makefile
.PHONY:cleanall
BIN=01test 02test
all=$(BIN)
clean:
rm –f 01test 02test
$ make
$makeclean
#Makefile
.PHONY:cleanall
BIN=01test 02test
all=$(BIN)
01test:01test.o
gcc –Wall –g 01test.o –o 01test
02test:02test.o
gcc –Wall –g 02test.o –o 02test
clean:
rm –f 01test 02test
$ make
$makeclean
#Makefile
.PHONY:cleanall
BIN=01test 02test
all=$(BIN)
%.o:%.c
gcc –Wall –g –c $^ -o $@
01test:01test.o
gcc –Wall –g 01test.o –o 01test
02test:02test.o
gcc –Wall –g 02test.o –o 02test
clean:
rm –f 01test 02test
$ make
$makeclean
#Makefile
.PHONY:cleanall
BIN=01test 02test
all=$(BIN)
.c.o:
gcc –Wall –g –c $^ -o $@
01test:01test.o
gcc –Wall –g 01test.o –o 01test
02test:02test.o
gcc –Wall –g 02test.o –o 02test
clean:
rm –f 01test 02test
$ make
$makeclean
#Makefile
.PHONY:cleanall
BIN=01test 02test
all=$(BIN)
CC=gcc
FLAGES=-Wall-g
.c.o:
$(CC) $( FLAGES) –c $^ -o $@
01test:01test.o
$(CC) $(FLAGES) 01test.o –o 01test
02test:02test.o
$(CC) $(FLAGES) 02test.o –o 02test
clean:
rm –f 01test 02test
$ make
$makeclean
$ touch03test.c
#Makefile
.PHONY:cleanall
BIN=01test 02test 03test
all=$(BIN)
CC=gcc
FLAGES=-Wall-g
.c.o:
$(CC) $( FLAGES) –c $^ -o $@
01test:01test.o
$(CC) $(FLAGES) 01test.o –o 01test
02test:02test.o
$(CC) $(FLAGES) 02test.o –o 02test
03test:03test.o
$(CC)$(FLAGES) 03test.o –o 03test
clean:
rm –f 01test 02test 03test
$ make
$makeclean
$ touchpub.c //03test 依赖与pub.c
$ touch03test.c
#Makefile
.PHONY:cleanall
BIN=01test 02test 03test
all=$(BIN)
CC=gcc
FLAGES=-Wall-g
.c.o:
$(CC) $( FLAGES) –c $^ -o $@
01test:01test.o
$(CC) $(FLAGES) 01test.o –o 01test
02test:02test.o
$(CC) $(FLAGES) 02test.o –o 02test
03test:03test.opub.o
$(CC) $(FLAGES) 03test.o pub.o–o 03test
clean:
rm –f *.o 01test 02test 03test
$ make
$makeclean
%.o:%.c 模式规则 .c.o: 后缀规则
Makefile(下)
一、多目录、单可执行文件生成
$ touchmain.c Makefile
$ mkdirdll ui bll
$ cd dll
$ touchdll.h dll.c
$ cd ..
$ cd ui
$ touchui.h ui.c
$ cd ..
$ cd bll
$ touchbll.h bll.c
//main.c
intmain()
{
return 0;
}
.PHONY:clean
CC = gcc
FLAGES =-Wall –g
BIN =main
ROOTDIR =$(shell find –d */)
ROOTSRC =$(wildcard *.c)
ROOTOBJ =$(ROOTSRC:%.c=%.o)
SUBSRC =$(shell find $(ROOTDIR) –name *.c)
SUBOBJ =$(SUBSRC:%.c=%.o)
$(BIN):$(ROOTOBJ)$(SUBOBJ)
$(CC) $(FLAGES) –o $(BIN) $(ROOTOBJ)$(SUBOBJ)
%.o:%.c
$(CC) $(FLAGES) -c $< -o $@
clean:
rm –f $(BIN) $(ROOTOBJ) $(SUBOBJ)
二、 多目录多执行文件生成(较难,暂时过)
gdb入门(上)
一、
//simple.c
#include<stdio.h>
#include<stdlib.h>
intfun(int n);
intmain()
{
int result = 0,I;
for(i=1;i<=100;i++)
{
result += I;
}
printf(“result[1-100]:%d\n”,result);
printf(“fun(10):%d\n”,fun(10));
return 0;
}
intfun(int n)
{
int I,sum = 0;
for(i=1;i<=n;i++)
{
sum += I;
}
return sum;
}
$ gcc –Wall–g simple.c –o simple //-g 表示可以生成详细的调试信息
$./simple
$ gdbsimple
(gdb)list //列出源代码简写l
(gdb)break 10 //在10行处设置断点简写b
(gdb)info break //列出断点信息简写i b
(gdb)break fun //在函数入口处设置断点
(gdb) runsimple //运行simple程序
(gdb)s //单步执行
(gdb) pi//查看变量i的值
(gdb)until //跳出循环
(gdb)continue //调到下一断点简写c
(gdb)finish //跳出一个函6570
(gdb)q //退出gdb
(gdb) runa b c //命令行参数
(gdb)list 1,20 //查看1-20的代码
(gdb)list fun//查看fun函数的代码
(gdb)list:simple.c:2,11 //查看某个文件的代码
(gdb)break 22 //在22行设置断点
(gdb)delete 1 //删除第一个断点
(gdb) bif i=50 //设置条件断点
(gdb)info break(i b) //查看断点
(gdb)watch i //设置观察点,但每次i改变时就打印其改变
(gdb) n//但不跟踪,但不进入函数
gdb入门(下)
//simple.c
#include<stdio.h>
#include<stdlib.h>
intfun(int n);
intmain()
{
int result = 0,I;
int x=2;
double d = 3.2;
int arr1[] = {0,1,2,3,4,5,6,7,8,9};
int *arr2 = (int*)malloc(10*sizeof(int));
for(i=0;i<10;i++)
{
arr2[i] = I;
}
for(i=1;i<=100;i++)
{
result += I;
}
printf(“result[1-100]:%d\n”,result);
printf(“fun(10):%d\n”,fun(10));
return 0;
}
intfun(int n)
{
int I,sum = 0;
for(i=1;i<=n;i++)
{
sum += I;
}
return sum;
}
一、ptype 变量名 //可以查看变量的类型
(gdb)ptype d;
(gdb)ptype arr;
p 变量名 //打印变量的值
(gdb) parr1; //打印数组
(gdb) parr1[3]
(gdb) p &arr1 //数组arr1的地址,与c语法稍有不同
(gdb) p&arr1[0] //数组arr1的地址
p*arr@n //打印动态数组arr的n个值
(gdb) p*arr2@10
(gdb) p*arr2@2
p i=1000//动态改变变量的值
三、调试逻辑错误
四、调试运行时错误,如段错误
五、core文件的使用
首先 ulimit –a查看状态
ulimit –c
ulimit –cunlimited
然后出现运行时错误时就会出现core 文件
gdb 可运行文件 core文件名
即可发现错误处
(gdb)bt错误调用情况