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专家编程

  • 相关阅读:
    如何将网格式报表打印成其它样式
    拥有与实力不相称的脾气是种灾难——北漂18年(23)
    8.8.1 Optimizing Queries with EXPLAIN
    mysql 没有rowid 怎么实现根据rowid回表呢?
    secondary index
    8.5.5 Bulk Data Loading for InnoDB Tables 批量数据加载
    mysql 中key 指的是索引
    8.5.4 Optimizing InnoDB Redo Logging 优化InnoDB Redo 日志
    8.5.3 Optimizing InnoDB Read-Only Transactions 优化InnoDB 只读事务
    8.5.1 Optimizing Storage Layout for InnoDB Tables InnoDB表的存储布局优化
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7268517.html
Copyright © 2011-2022 走看看