执行时的C程序
数据和代码
编程语言理论经典对立之中的一个就是代码和数据的差别。有些语言如LISP把两者视为一体,其它语言如C语言则维持两者的差别。编译绝大部分工作都跟翻译代码有关,必要的数据存储管理的绝不部分都在执行时进行。
学习执行时能够有三个优点,有助于优化代码。获得最佳效率,有助于理解更高级的材料。陷入麻烦的时候。能够更easy的分析问题。
段(Segments)
ELF:(原意为Extensibla Linker Format,可扩展链接器格式,如今代表Executable and Linking Format,可执行文件和链接格式),存在于绝大多SVr4实现。
COFF:(Common Ojbect-File Format,普通目标文件格式)。存在于其它系统中。
上述两种不同的格式有一个共同的概念,段。段的概念和非常多都相关,单就目标文件而言,段就是指二进制文件里简单的区域,里面保存了和某种特定类型(如符号表条目)相关的信息。
术语Section也被广泛使用。section是ELF文件里的最小组织单位。一个段一般包含几个section。
上述段的概念是UNIX中的。和Intel X86架构的段全然没有关系。UNIX中段就表示一个二进制文件的内容块,intel X86中段表示一种设计的结果,在这样的设计中,地址空间并非一个总体,而是分成64k大小的区域,称之为段,这样的设计也是情非得已,为了向下兼容以前的芯片。
a.out的结构
下图显示了编译器和连接器分别在这些段中写入了什么东西
BSS段是“Block Started by Symbol(由符号開始的块)”的缩写。它是旧式IBM704汇编程序的一个伪指令,UNIX借用了这个名字。至今仍然沿用。有些人喜欢把它记作“Better Save Space(更有效的节省空间)”,由于BSS段仅仅保存没有值得变量,所以其实并不须要保存这些变量的映象。执行时所须要的BSS段的大小记录在目标文件里。但BSS段不像其它段。它并不占用目标文件的不论什么空间
能够使用size命令和nm程序来查看程序各个部分的大小
操作系统之于a.out
为什么要用段来组织,由于段能够方便的映射到链接器。在执行时能够直接加载。加载器仅仅须要提取文件里每一个段的映像。段在正在执行的程序中是一块内存区域,每一个区域有特定的目的。
文本段包含程序的指令
数据段包含经过初始化的全局变量和静态变量以及它们的值,BSS段的大小从可执行文件里得到。然后链接得到这个大小的内存块。紧跟数据块之后,这块内存进入程序后所有清零。
C语言执行时系统之于a.out
执行时数据结构包含,堆栈、活动记录、数据和堆等
- 堆栈段:主要有三个用途。和函数以及表达式有关。
除了递归调用,堆栈并非必须的。在大多数CPU中,堆栈是向下增长的,也就是朝着低地址方向生长。
- 为函数内部的局部变量提供存储空间
- 函数调用过程中,保持一些维护性信息,称为堆栈结构或者过程活动记录
- 暂存区,非常长的算数表达式
和C++不同。C执行时函数个个短小精悍,使得C非常高效
C语言不同意在函数中定义函数,也就是函数不能嵌套定义。
setjmp和longjmp
以上两个命令是C语言独有的,通过操纵过程活动记录实现的。
- setjmp(jmp_buf j)必须首先被调用。它表示使用变量j记录如今的位置,函数返回0;
- longjmp(jmp_buf j,int i)能够接着被调用。它表示回到j所记录的位置,让他看上去像刚从setjmp函数返回一样。可是函数返回i。使代码知道它实际上是通过longjmp返回的。
- 当使用longjmp时。j的内容被销毁
- setjmp保存了一份程序计数器和当前的栈顶指针,也能够保存一些初始值,longjmp恢复这些初始值。
- 和goto不同,第一,goto不能跳出C语言的函数;第二。longjmp仅仅能回到以前到过的地方。
- 须要注意的是。保证局部变量在longjmp过程中一直保持它的值得唯一可靠办法就是把它声明为volatile。
- 两者组合最大用途是错误恢复。仅仅要还没从函数返回,一旦发现一个不可恢复的错误,就能够把控制流转移到主输入循环。能够用它来从一串非常深的代码中马上返回,提防潜在的危急代码。
眼下C++已经支持了异常系统
switch(setjmp(jbuf))
{
case 0:
apple = *suspicious;
break;
case 1:
printf("suspicious is a bad pointer\n");
break;
default:
die("unexpected value returned bt setjmp");
}
- 和goto一样。不是必要的情况下不要使用它们。
UNIX和MS-DOS的堆栈段
- 在UNIX中,当进程须要很多其它空间的时候,堆栈会自己主动生长。
- DOS中,在建立可执行文件时,堆栈大小必须同一时候确定,并且它不能在执行时增长。Stack overflow是常见的堆栈溢出错误。
实用的C语言工具
Reference
C专家编程
执行时的C程序的更多相关文章
- C#获取程序代码执行时长
ArrayList list = new ArrayList(); long startTicks = DateTime.Now.Ticks; for (int i = 0; i < 10000 ...
- 承载(Host)通用语言执行时
承载(Host)通用语言执行时(CLR) 还有一种使用COM 的方法是是把须要集成的 F# 代码与已有的 C/C++ 应用程序集成到一起.开成自己定义的承载通用语言执行时.通用语言执行时就是 C++ ...
- py文件控制台执行时,报错:引入的模块不存在
1.描述:该模块在IDE中是可以正确执行的.但是从cmd控制台执行时,报错:该模块引入的其他模块不存在. 2.解决:在该模块的#encoding:utf-8 之后另起一行加如下代码: #encodin ...
- Android执行时ART载入OAT文件的过程分析
在前面一文中,我们介绍了Android执行时ART,它的核心是OAT文件.OAT文件是一种Android私有ELF文件格式,它不仅包括有从DEX文件翻译而来的本地机器指令.还包括有原来的DEX文件内容 ...
- java中多线程执行时,为何调用的是start()方法而不是run()方法
Thead类中start()方法和run()方法的区别 1,start()用来启动一个线程,当调用start()方法时,系统才会开启一个线程,通过Thead类中start()方法来启动的线程处于就绪状 ...
- 【java】计算一段代码执行时长java.lang.System类里的public static long currentTimeMillis()方法
public class Test_currentTimeMillis { public static void main(String[] args) { long start=System.cur ...
- DbCommandInterceptor抓取EF执行时的SQL语句
EF6.1也出来不少日子了,6.1相比6.0有个很大的特点就是新增了System.Data.Entity.Infrastructure.Interception 命名空间,此命名空间下的对象可以允许我 ...
- html 事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。
看一个简单的例子: html: <head> <meta charset="UTF-8"> <title>Document</title& ...
- 用字符串连接SQL语句并用EXEC执行时,出现名称 '‘不是有效的标识符
原文:用字符串连接SQL语句并用EXEC执行时,出现名称 ''不是有效的标识符 用字符串连接SQL语句并用EXEC执行时,出现名称 '这里是字符串连接的一条SQL语句‘不是有效的标识符 才发现,在写e ...
随机推荐
- 【C++】多重继承
1. 多重继承时的二义性 当使用多重继承时,如果多个父类都定义了相同名字的变量,则会出现二义性.解决方法:使用 :: 声明作用域 #include <iostream> using nam ...
- Selenium2+python自动化54-unittest生成测试报告(HTMLTestRunner)【转载】
前言 批量执行完用例后,生成的测试报告是文本形式的,不够直观,为了更好的展示测试报告,最好是生成HTML格式的. unittest里面是不能生成html格式报告的,需要导入一个第三方的模块:HTMLT ...
- Android 使用WebView控件展示SVG图
1.添加布局界面代码: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xm ...
- Linux上安装Redis教程
Redis的安装步骤: 步骤1.安装redis必须已经安装了gcc,如果没安装gcc 就使用命令 yum install -y gcc步骤2.下载redis包 下载地址:http://download ...
- web模拟telnet
https://blog.csdn.net/midion9/article/details/51781402 https://blog.csdn.net/hackstoic/article/detai ...
- win上使用nvm管理node版本
win上使用nvm管理node版本 若想让nvm管理机器上所有的node版本,首先需要卸载电脑上已有的node(很重要), 然后下载nvm在win上的安装包 windows-nvm的下载地址 下载 下 ...
- Bellman - Ford 算法解决最短路径问题
Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...
- 21、Flask实战第21天:常用的Flask钩子函数
在Flask中钩子函数是使用特定的装饰器装饰的函数.为什么叫钩子函数呢?是因为钩子函数可以在正常执行的代码中,插入一段自己想要执行的代码.那么这种函数就叫做钩子函数. before_first_req ...
- Java中String对象的创建
字符串对象是一种特殊的对象.String类是一个不可变的类..也就说,String对象一旦创建就不允许修改 String类有一个对应的String池,也就是 String pool.每一个内容相同的字 ...
- 求一个整数个位数之和 Exercise06_02
import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:求一个整数个位数之和 * */ public class Exercise ...