静态库和共享库(动态库) 动态调用共享库 C的错误处理
2016-06-12 19:30
309 查看
一 静态库和共享库(动态库)
1 静态库和共享库简介
由于项目比较复杂,代码数量非常庞大,可以把代码打包成库文件,提供库文件和头文件即可。库文件分为两种:
静态库和共享库(动态库),静态库和共享库都是代码的归档文件。使用静态库时,把静态库的代码复制到目标文件中,导致目标文件比较大;使用共享库时,把函数的地址放到目标文件中。
静态库和共享库的优缺点:
静态库的优点:目标文件独立于库文件,运行速度稍快。缺点:目标文件比较大,不利于代码的修改、扩展和复用。
共享库的优点:目标文件比较小,修改、扩展和复用代码比较方便。缺点:目标文件必须和共享库文件同时存在,代码才能正常运行。运行速度稍慢。
开发多半使用 共享库。
2 静态库的使用
使用静态库的步骤:2.1 创建静态库(.a)
1 写源程序 add.c 保存退出2 编译源程序,得到 .o 文件(gcc -c)
3 创建静态库文件:
ar -r libXX.a add.o
注:lib开头 .a结束是静态库的命名规范。XX是库名
创建静态库文件后,还需要提供 .h文件。
2.2 使用静态库
1 写调用源程序 test.c,保存退出2 编译test.c,只编译不连接(gcc -c)
3 连接 test.o 和静态库文件。
连接方式有三种:
a 直接连接
gcc test.o libXX.a
b 配置环境变量LIBRARY_PATH,把库文件所在路径放入其中,然后:
gcc test.o -lXX
c gcc test.o -lXX -L所在路径 (双L,推荐)
add.h #ifndef ADD_H_ #define ADD_H_ int add(int,int); double add2(double,double); #endif
add.c int add(int a,int b){ return a+b; } double add2(double a,double b){ return a+b; }
test.c #include <stdio.h> #include "add.h" //#include <add.h> int main(){ int r = add(2,3); double d = add2(1.0,4.0); printf("r=%d,d=%lf\n",r,d); }
3 共享库的使用
使用共享库的步骤:3.1 创建共享库
1 写源程序add.c,保存退出2 编译
gcc -c -fpic add.c (不写-fpic也行)
3 生成共享库
gcc -shared add.o -olibXX.so
注:共享库也需要提供头文件
gcc -fpic -shared add.c -o libadd.so,这一条命令生成库也行
3.2 使用共享库
和静态库方式一样。注:连接成功后,需要配置LD_LIBRARY_PATH才能运行成功。
ldd 命令可以查看 使用的共享库。
二 动态调用共享库(动态编程)
代码在运行时才知道调用哪个函数,执行哪段代码相关函数:
dlopen() dlsym() dlclose()
错误处理 dlerror()
dlopen:打开共享库文件
dlclose: 关闭共享库文件
dlsym: 从一个打开的库文件中获得一个函数,返回函数指针
dlopen()第一个参数是 共享库的文件名,第二个参数是加载方式:
RTLD_LAZY - 延迟加载,open时不加载,使用时加载
RTLD_NOW - open文件的同时加载
返回 库文件的首地址。
man 查看帮助手册,Linux下英文翻译软件:星际译王
dl.c #include <stdio.h> #include <dlfcn.h> int main(){ void* handle = dlopen("./libmyku.so", RTLD_NOW); char* error = dlerror(); if(error/*!=NULL*/){//!=NULL可以省略 printf("open error\n"); return -1; } double (*f)(double,double);//换一下函数名 f = dlsym(handle,"add2"); double d = f(2.0,4.0); printf("d=%lf\n",d); dlclose(handle); }//gcc dl.c -ldl
三 C的错误处理
C程序没有异常,因此错误处理有自己的一套机制,用返回值的不同体现错误:1 返回指针类型,一般用NULL代表错误。
2 返回int类型,返回数据不可能是-1,一般用-1代表错误。
3 返回int类型,但返回数据有可能是-1,用指针取回数据,用返回 -1 代表错误,返回0 代表正确。
4 如果不需要考虑错误处理,返回值为void。
以上4种情况都是一般用法(惯例),都有特殊情况。
练习:
有4个函数,实现代码和错误处理
a 打印传入的字符串 4
b 测试传入字符串的值,如果不是error,返回ok,如果是error,代表出错,处理函数错误。 1
c 返回0-10的随机数,如果随机到5,代表出错 2
d 求两个整数的最大值,如果相等,代表出错。3
err.c #include <stdio.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <errno.h> void print(char* str){ printf("%s\n",str);//\n换行,不会不打印 } char* iferror(char* str){ if(strcmp(str,"error")==0){ return NULL;//“NULL” NULL不同 }//前者是具体字符串 NULL才是空 return "OK"; } int getrand(){ srand(time(0)); int r = rand()%11; if(r == 5) return -1; /*else*/ return r; } int max(int a,int b,int *pi){ if(a == b) return -1; *pi = (a>b)?a:b; } int main(){ print("hello"); char* s = iferror("eror"); if(s == NULL){ printf("出错了\n"); return -1; } printf("%s\n",s); int r = getrand(); if(r == -1) { printf("rand出错了\n"); return -1; } printf("r=%d\n",r); int maxi; r = max(2,2,&maxi); if(r == -1) { printf("max出错了\n"); printf("errno=%d\n",errno); return -1; } printf("max=%d\n",maxi); }
C对于错误处理提供了一个外部全局变量,三个函数:
errno - 错误的编号,不包括错误信息
strerror() - 把错误编号 转换成 错误信息
perror() -自动找到错误编号并打印对应的错误信息
printf() -“%m”自动打印错误信息
最常用的错误处理函数就是 perror()。
perror()允许传入一些附加信息,帮助程序员定位哪里出了错误。
errno 是一个全局变量,可以直接使用。使用方式:成功不改变值,失败设置值。不是所有的函数都使用errno处理错误。
perror.c #include <stdio.h> #include <errno.h> #include <string.h> int main(){ FILE* file=fopen("/etc/passwd1","r"); printf("errno=%d\n",errno); if(file == NULL){ //printf("open:%s\n",strerror(errno)); //printf("oepn: %m\n"); perror("open passwd1"); //return -1; } else { printf("open ok\n"); } file = fopen("/etc/passwd","r"); printf("errno=%d\n",errno); }
相关文章推荐
- Codeforces Round #355 (Div. 2) D. Vanya and Treasure
- 【bzoj1086】[SCOI2005]王室联邦 树分块
- 搜索(DLX):HDU 3663 Power Stations
- 关于内存问题提醒!结构体+protobuf做协议体发送!
- TIJ 复习笔记5
- hibernate循环插入数据
- IntelliJ Idea 常用快捷键列表
- Bootstrap排版
- Bootstrap排版
- leetcode 355 Design Twitte
- 集群配置虚拟主机及部署Hadoop集群碰到的问题
- C和C++中struct的区别 以及C++中struct和class 以及c和c++区别 引用和指针
- BZOJ 1497 最大获利(最大权闭合子图)
- myeclipse中创建struts2的web项目
- 学习进度条十四
- apache配置
- c primer plus第3章总结:数据类型
- 使用DOM4J修改读入的xml文档
- 项目经验教训总结
- hive脚本出现Error: java.lang.RuntimeException: Error in configuring object和Caused by: java.lang.IndexOutOfBoundsException: Index: 9, Size: 9