zoukankan      html  css  js  c++  java
  • 执行时的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
    ");
              break;
        default:
              die("unexpected value returned bt setjmp");
    }
    • 和goto一样。不是必要的情况下不要使用它们。

    UNIX和MS-DOS的堆栈段

    • 在UNIX中,当进程须要很多其它空间的时候,堆栈会自己主动生长。
    • DOS中,在建立可执行文件时,堆栈大小必须同一时候确定,并且它不能在执行时增长。Stack overflow是常见的堆栈溢出错误。

    实用的C语言工具

    这里写图片描写叙述
    这里写图片描写叙述

    Reference

    C专家编程

  • 相关阅读:
    cf 1452E. Two Editorials(中点排序)
    cf 888G
    cf 1447E. Xor Tree(二进制分治)
    2020ICPC·小米 网络选拔赛第一场 E-Phone Network (线段树)
    cf 1447D. Catching Cheaters ( 最大子段和思想 dp )
    POJ
    cf 1437F.Emotional Fishermen(计数dp)
    霍夫丁不等式
    切比雪夫不等式
    霍夫丁不等式引理证明
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7268517.html
Copyright © 2011-2022 走看看