Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / 动静态GCC编译case1

源文件(这是Rechard Steven在unix 高级编程的代码)
# cat liberr.h
#ifndef _LIBERR_H
#define _LIBERR_H#include <stdarg.h>
#define MAXLINELEN 4096void err_ret(const char *fmt, ...);void err_quit(const char *fmt, ...);void log_ret (char *logfile,const char *fmt, ...);void log_quit(char *logfile,const char *fmt, ...);void err_prn(const char *fmt,va_list ap, char *logfile);#endif
# cat liberr.c
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "liberr.h"void err_ret(const char *fmt, ...)
{
 va_list ap; va_start(ap,fmt);
 err_prn(fmt,ap,NULL);
 va_end(ap);
 return;
}void err_quit(const char *fmt, ...)
{
 va_list ap;
 va_start(ap, fmt);
 err_prn(fmt, ap, NULL);
 va_end(ap);
 exit(EXIT_FAILURE);
}void log_ret(char *logfile,const char *fmt, ...)
{
 va_list ap;
 
 va_start(ap,fmt);
 err_prn(fmt,ap,logfile);
 va_end(ap);
 return;
}void log_quit(char * logfile,const char *fmt, ...)
{
 va_list ap; va_start(ap,fmt);
 err_prn(fmt,ap,logfile);
 va_end(ap);
 exit(EXIT_FAILURE);
}extern void err_prn(const char *fmt, va_list ap, char *logfile)
{
 int save_err;
 char buf[MAXLINELEN];
 FILE *plf; save_err=errno;
 vsprintf(buf,fmt,ap);
 sprintf(buf + strlen(buf),":%s",strerror(save_err));
 strcat(buf," ");
 fflush(stdout);
 if(logfile != NULL)
  if((plf = fopen(logfile,"a")) != NULL ) {
    fputs(buf,plf);
    fclose(plf);
  } else
    fputs("failed to open log file ,", stderr);
 else
    fputs(buf,stderr);
 fflush(NULL);
 return;
}
编译及打包静态包
#gcc -c liberr.c -o liberr.o
#ar rcs liberr.a liberr.o
# cat errtest.c
#include <stdio.h>
#include <stdlib.h>
#include "liberr.h"#define ERR_QUIT_SKIP 1
#define LOG_QUIT_SKIP 1int main(void)
{
 FILE *pf;
 
 puts("Tesing err_ret");
 if((pf = fopen("foo","r")) == NULL) {
  err_ret("%s %s","err_ret:","failed to open foo");
 } puts("Tesing log_ret");
 if((pf = open("foo","r")) == NULL) {
  log_ret("errtest.log","%s %s","log_ret:","failed to open foo");
 }#ifndef ERR_QUIT_SKIP
puts("Testing err_quit");
if((pf = open("foo","r")) == NULL) {
 err_ret("%s %s","err_ret:","failed to open foo");
}
#endif
#ifndef LOG_QUIT_SKIP
puts("Testing log_quit");
if((pf = open("foo","r")) == NULL) {
 log_ret("errtest.log","%s %s","log_quit:","failed to open foo");
}
#endifexit(EXIT_SUCCESS);
}
静态库编译:
[root@pc201 linux_guide]# gcc errtest.c -o errtest -L. -lerr --static
errtest.c: In function ‘main’:
errtest.c:18: warning: assignment makes pointer from integer without a cast
/usr/bin/ld: cannot find -lc
collect2: ld returned 1 exit status解决办法是安装glibc-static
[root@pc201 linux_guide]# yum install glibc-static
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.163.com
 * extras: mirrors.163.com
 * updates: ftp.stu.edu.tw
Setting up Install Process
Resolving Dependencies
--> Running transaction check
....      .....      ..........
Complete!再次运行就没有报错了
[root@pc201 linux_guide]# gcc errtest.c -o errtest -L. -lerr --static
errtest.c: In function ‘main’:
errtest.c:18: warning: assignment makes pointer from integer without a cast
与动态库分析:
建立动态库:
#gcc -fPIC -g -c liberr.c -o liberr.o
#gcc -g -shared -Wl,soname,liberr.so -o liberr.so.1.0.0 liberr.o -lc
动态链接编译的结果静态编译的结果看到比动态链接的大接近100倍。下面示例调用动态库内部的函数。这里,我们要调用liberr.so里的err_ret函数:# cat dltest.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>int main(void)
{
 void *handle;
 void (*errfcn) (const char *fmt, ...);    //errfcn是函数指针,它要指向要调用的err_ret
 const char *errmsg;
 FILE *pf;
 
 handle = dlopen("./liberr.so",RTLD_NOW); // dlopen打开liberr.so,返回handle
 if(handle==NULL) {
  fprintf(stderr,"Failed to load liberr.so:%s ",dlerror());
  exit(EXIT_FAILURE);
 }
 dlerror();                              // reset dl error
 errfcn=dlsym(handle,"err_ret");        // dlsym 寻找handle里的err_ret函数
 if((errmsg = dlerror()) != NULL) {     
  fprintf(stderr,"Didn"t find err_ret:%s ",errmsg);
  exit(EXIT_FAILURE);
 } if((pf = fopen("foobar","r")) == NULL) {
  errfcn("Couldn"t open foobar");
 }
 
 dlclose(handle);                        //关闭handle
 exit(EXIT_FAILURE);
}编译
gcc -g dltest.c -Wall -ldl -o dltest执行结果无结果,调试:发现代码少了一段
 if((pf = fopen("foobar","r")) == NULL) {
  errfcn("Couldn"t open foobar");
 }
加进去,编译,执行Unix环境高级编程 源代码地址 http://www.linuxidc.com/Linux/2011-04/34826.htmUnix环境高级编程源码编译 http://www.linuxidc.com/Linux/2011-09/42503.htmapue.h头文件(Unix环境高级编程) http://www.linuxidc.com/Linux/2012-01/51729.htm《Unix环境高级编程》(第二版)apue.h的错误 http://www.linuxidc.com/Linux/2011-04/34662.htmUnix环境高级编程第二版读书笔记 http://www.linuxidc.com/Linux/2011-04/34235.htm《Unix环境高级编程》中apue.h的问题 http://www.linuxidc.com/Linux/2013-01/77686.htmLinux升级GCC 4.8.1清晰简明教程(Ubuntu 12.04 64位版为例)  http://www.linuxidc.com/Linux/2014-04/99583.htm Ubuntu下Vim+GCC+GDB安装及使用 http://www.linuxidc.com/Linux/2013-01/78159.htm Ubuntu下两个GCC版本切换 http://www.linuxidc.com/Linux/2012-10/72284.htm CentOS6.5升级手动安装GCC4.8.2  http://www.linuxidc.com/Linux/2015-01/112595.htm GCC 的详细介绍:请点这里本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-03/129630.htm