body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;} th{border: 1px solid gray; padding: 4px; background-color: #DDD;} td{border: 1px solid gray; padding: 4px;} tr:nth-child(2n){background-color: #f8f8f8;}
Linux 下文件编译与调试
gcc/g++编译器
对于.c格式的 C文件,可以采用gcc或g++编译
对于 .cc、.cpp格式的C++文件,应该采用g++进行编译
|
常用的选项:
-c 表示编译源文件
-o 表示输出目标文件
-g 表示在目标文件中产生调试信息,用于gdb调试
-D <宏定义> 编译时将宏定义传入进去
-Wall 打开所有类型的警告。
|
|
1. gcc编译过程:预编译->编译->汇编->链接 |
(1)预处理:预处理器将对源文件中的宏进行展开。
(2)编译:gcc将c文件编译成 汇编文件。
(3)汇编:汇编器as将汇编文件编译成机器码。
(4)链接:将目标文件和外部符号进行连接,得到一个可执行二进制文件。
//test.c
|
|
(1)预处理: gcc –E test.c -o test.i
我们用 cat 查看 test.i 的内容如下:int main() int x=(1+2); return 0;我们可以看到,文件中宏定义NUMBER出现的位置被(1+2)替换掉了,其它的内容保持不变。
预处理阶段:对包含的头文件(#include)和宏定义(#define、#ifdef等)进行处理
|
(2)编译:gcc -S test.i –o test.s 通过 cat test.s 查看 test.s 的内容为代码。
编译阶段:检查代码规范性、语法错误等,在检查无误后把代码翻译成汇编语言
|
|
(3)汇编:as test.s -o test.o 利用as将汇编文件编译成机器码。得到输出文件为 test.o。test.o 中为目标机器上的二进制文件. 用 nm 查看文件中的符号: nm test.o 输出如下:0000000000000000 T main。既然已经是二进制目标文件了,能不能执行呢?试一下 ./test.o,提示 cannotexecute binary file.T表示这个符号属于代码。
//test.o 得先加一个执行权限
|
(4)链接: gcc test.o –o test ,将所有的.o文件链接起来生产可执行程序。 链接阶段:将.s的文件以及库文件整合起来链接为可执行程序 |
gcc所支持后缀名: |
gcc常用选项: |
gcc库选项: |
gcc警告选项: |
file 文件名 看对应文件类型 gcc -v 显示编译器版本 |
//test1.c
#include<stdio.h>
int main()
{
#ifdef meihao
printf("define meihao\n");
#else
printf("not define meihao\n");
#endif
printf("main exit\n");
}
|
gcc -E test1.c -o test1.i gcc -E test1.c -o test1.i -D meihao |
静态库是目标文件.a 的归档文件(格式为libname.a)。如果在编译某个程序时链接静态库,则链接器将会搜索静态库并直接拷贝该程序的可执行二进制文件到当前文件中;
静态库将会整合到程序中,在程序执行时不用加载静态库。 因此,静态库会使你的程序臃肿并且难以升级,但比较容易部署。而动态库会使你的程序轻便易于升级但难以部署。
|
动态库(格式为 libname.so[.主版本号.次版本号.发行号])。在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入。
动态库只在执行时才被链接使用,不是直接编译为可执行文件,并且一个动态库可以被多个程序使用故可称为共享库。
|
|
创建静态库: >gcc -c add.c //编译add.c源文件生成add.o目标文件 >ar -crsv libadd.a add.o //对目标文件*.o进行归档,生成lib*.a,此处lib要写;命令参数: c 创建一个库。不管库是否存在,都将创建。 r 代替库中现有的文件或者插入新的文件 s 写入一个目标文件索引到库中,或者更新一个存在的目标文件索引 v 输出详细信息 a - add.o >su #cp ./libadd.a /lib //拷贝到标准程序设计库 >gcc main.c -w -o main -ladd >./main 1 2
sum=3
>gcc -c add.c
>ar -crsv libadd.a add.o
a - add.o
>gcc main.c -w -o main -L./ -ladd //不要忘记-L后面的那个./ ;即在库文件的搜索路径中添加当前路径 -ladd表示链接库文件libadd.a/.so
>./main 1 2
sum=3
|
创建动态库:
>gcc -fPIC -Wall -c add.c //编译,允许发出警告,生成使用相对地址的位置无关的目标代码
>gcc -shared -o libadd.so add.o //生成库文件libadd.so
>su
#cp ./libadd.so /lib
#exit //拷贝到 /lib 库中
>gcc main.c -w -o main -ladd
>./main 1 2
sum=3
在运行main前,需要注册动态库的路径。
方法有3种:
▶修改/etc/ld.so.conf
▶修改LD_LIBRARY_PATH环境变量
▶将库文件拷贝到/lib或者/usr/lib下(系统默认搜索库路径)。 |
|
//add.c int add(int a,int b)
{
return a+b;
}
|
//main.c #include<stdio.h>
#include<stdlib.h>
void main(int argc,char* argv[])
{
if(argc!=3)
{
printf("error args\n");
return;
}
int i=atoi(argv[1]);
int j=atoi(argv[2]);
printf("sum=%d\n",add(i,j));
}
|
程序调试
gdb常用命令
Linux 包含了一个叫gdb的调试程序。gdb可以用来调试 C 和 C++ 程序。在程序编译时用 -g 选项可打开调试选项,表示在目标文件中产生调试信息,用于gdb调试;
>gcc test1.c -Wall -g -o test //(—g和—o要挨在一起)(—g和—c要挨在一起)
>gdb ./test
|
>ulimit -c unlimited |
>gcc test3.c -w -o test3
>gdb ./test3 core
//l 输出错误行代码,bt 打开调用栈查看自己错误行代码, q 退出;
|
//test3.c #include<stdio.h>
int add(int a,int b)
{
return a+b;
}
int main(int argc,char **argv)
{
int i,j,sum;
i=atoi(argv[1]);
j=atoi(argv[2]);
sum=add(i,j);
printf("sum=%d\n",sum);
}
|
gcc对代码进行优化通过选项“-On”来控制优化级别(n是整数)。不同的优化级别对应不同的优化处理工作。如使用优化选项“-O1”主要进行线程跳转和延迟退栈两种优化。使用优化选项“-O2”除了完成所有“-O1”级别的优化之外,还要进行一些额外的调整工作,如处理其指令调度等。选项“-O3”则还包括循环展开或其他一些与处理器特性相关的优化工作。虽然优化选项可以加速代码的运行速度,但对于调试而言将是一个很大的挑战。因为代码在经过优化之后,原先在源程序中声明和使用的变量很可能不再使用,控制流也可能会突然跳转到意外的地方,循环语句也有可能因为循环展开而变得到处都有,所有这些对调试来讲都是不好的。所以在调试的时候最好不要使用任何的优化选项,只有当程序在最终发行的时候才考虑对其进行优化。
通常用的是-O2
|
LINUX下文件编译的更多相关文章
-
嵌入式之:Linux下文件编译过程
本文主要三个部分:1.GNU GCC简介 2.C/C++交叉编译器arm-elf-gcc 3.make文件,用于工程管理 部分一:GNU GCC简介: 该编译器基本功能: (1)输出预处理后的文件(展 ...
-
dos2unix,去掉Linux下文件中的^M
Windows系统下使用VS2010编写好的CPP文件,想放到Linux上进行编译.发现Linux上文件中的每行代码末尾都跟着^M这个符号. 为什么同一份文件在windows上和Linux上显示的不一 ...
-
ACE-6.1.0 linux 下的编译与安装步骤
ACE-6.1.0 linux 下的编译与安装步骤 引用至http://www.cnblogs.com/liangxiaxu/archive/2013/03/07/2948417.html 1.从 ...
-
linux 下文件误删恢复
linux 下文件误删恢复 0x01 事件背景 某天晚上写代码的时候,本来想删除当前目录下一个叫xxx的文件夹 rm -rdf ./xxx/*, 结果光顾着和人说话,一不留神手贱把命令敲成了rm -r ...
-
FFmpeg在Linux下安装编译过程
转载请把头部出处链接和尾部二维码一起转载,本文出自:http://blog.csdn.net/hejjunlin/article/details/52402759 今天介绍下FFmpeg在Linux下 ...
-
Linux下nginx编译安装教程和编译参数详解
这篇文章主要介绍了Linux下nginx编译安装教程和编译参数详解,需要的朋友可以参考下 一.必要软件准备1.安装pcre 为了支持rewrite功能,我们需要安装pcre 复制代码代码如下: # y ...
-
linux下将编译错误输出到一个文本文件
linux下将编译错误输出到一个文本文件 command > filename 把把标准输出重定向到一个新文件中 command > > filename 把把标准输出重定向到一个文 ...
-
从四个问题透析Linux下C++编译&;链接
摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...
-
Linux下文件的三种时间戳
Linux下文件的三种时间标记 三种时间对应关系表 column column column 访问时间 Access atime 修改时间 Modify mtime 状态改动时间 Change cti ...
随机推荐
-
WEB UI 整理
当下对于网站前段开发人员来说,很少有人不使用一些JS框架或者WEB UI库,因此这些可以有效提高网站前段开发速度,并且能够统一开发环境,对于不同浏览器的兼容性也不需要程序员操心,有了这些优点,当然大家 ...
-
使用Memcached提高.NET应用程序的性能
在应用程序运行的过程中总会有一些经常需要访问并且变化不频繁的数据,如果每次获取这些数据都需要从数据库或者外部文件系统中去读取,性能肯定会受到影响,所以通常的做法就是将这部分数据缓存起来,只要数据没有发 ...
-
jQuery $.extend() 和 $.fn.extend() 用法
http://blog.csdn.net/xuemoyao/article/details/19021659
-
Android 随想录之 Android 系统架构
应用层(Application) Android 的应用层由运行在 Android 设备上的所有应用程序共同构成(系统预装程序以及第三方应用程序). 系统预装应用程序包含拨号软件.短信.联系人.邮件客 ...
-
struts2,登录功能模块实现
功能: ·UserLogin作为控制登录的Action,校验密码成功后记录session,可以选择记住登陆状态,登陆成功后自动跳转到登陆前的URL: ·UserLogout作为控制登录推出的Actio ...
-
寒假的ACM训练三(PC110107/UVa10196)
#include <iostream> #include <string.h> using namespace std; char qp[10][10]; int result ...
-
Chapter 2 Open Book——11
"Hey, Dad, welcome home." hey爸爸,欢迎回家. "Thanks." He hung up his gun belt and step ...
-
linux --- 7. 路飞学城部署
一.前端 vue 部署 1.下载项目的vue 代码(路飞学城为例), wget https://files.cnblogs.com/files/pyyu/07-luffy_project_01.zip ...
-
spring cloud config安全
前面两篇介绍了spring cloud config服务端和客户端的简单配置,本篇介绍如何保护config server及对应config client修改. 保护config server,主要是使 ...
-
SecureCRT修改显示行数
Scrollback buffer应该是保留的行数,初始值500,修改成自己想要的数值保存即可. 参考:http://blog.csdn.net/w410589502/article/details/ ...