其他分享
首页 > 其他分享> > 备用面试题

备用面试题

作者:互联网

1、C程序代码编译、运行全过程解析

很多嵌入式初学者,不明白一个简单的C语言程序,是如何通过一步步编译、链接变成一个可执行文件的,程序到底是怎么运行的?运行的过程中需要什么环境支持?

今天就跟大家一起捋一捋这个流程,搞清程序编译、链接、加载、运行的整个脉络,以及程序在运行过程中的内存布局、堆栈变化。

  1. 程序的编译、链接过程
    就以hello.c为例:从一个C语言源文件,到生成最后的可执行文件,基本流程如下:
    C 源文件:编写一个简单的helloworld程序
    预处理:生成预处理后的C源文件 hello.i
    编译:将C源文件翻译成汇编文件 hello.s
    汇编:将汇编文件汇编成目标文件 hello.o
    链接:将目标文件链接成可执行文件
    在这里插入图片描述
    为了加深对这个过程的理解,我们可以在Linux环境下面,通过gcc命令精确控制每一个编译、链接过程
$  gcc  -E  hello.c  >  hello.i  //会生成预处理后的C源文件hello.i
$  gcc  -S  hello.i              //将hello.i编译成汇编文件hello.s
$  gcc  -c  hello.s              //将汇编文件hello.s汇编成hello.o
$  gcc hello.o  -o hello         //将目标文件链接成可执行文件hello
$  ./hello                       // 运行可执行文件hello
  1. 程序的执行过程

当我们在shell交互环境下敲击 $ ./hello,这个hello程序到底是怎么运行的呢?

很简单。shell会首先通过系统调用fork创建一个子进程,然后从磁盘上将可执行文件hello的代码段、数据段加载(map)到这个子进程的地址空间内,接下来,在操作系统调度器的调度下,各个进程轮流占用CPU,就可以直接执行了。
在这里插入图片描述

  1. 进程的虚拟空间和物理空间
  1. 进程栈
  1. 用户栈、内核栈、中断栈
  1. 小结

参考:C语言编译链接加载过程

参考:C/C++的编译和链接过程

2、变量,常量,静态变量存储的位置

常见的存储区域可分为:

1、栈

由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。

2、堆

由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,程序会一直占用内存,导致内存泄漏,在程序结束后,操作系统会自动回收。

3、自由存储区

由malloc等分配的内存块,它和堆是十分相似的,不过它是用free来释放分配的内存。

4、全局/静态存储区

全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

5、常量存储区

这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改)。

参考:变量,常量,静态变量存储的位置

.file header

.text section

.data section

.bss section

这里主要分析以下每个字段的内容。

file header字段里存放了描述整个文件的基本属性信息的内容,如程序入口地址,其他各段信息(偏移量和范围)

.text section:主要是编译后的源码指令,是只读字段。

.data section :初始化后的非const的全局变量变量或者局部static变量。

.bss:未初始化后的非const全局变量和局部static变量。

另外,还有一些其他字段:如.rodata字段和.comment字段分别存放只读数据和注释部分。
用书上提供的例子做测试:

#include <stdio.h>
int global_init_val = 84;//.data
int global_uninit_val;
char b[]="aaa";//.data
char c[]="dddd";//.data
const char e[]="yyyy";//g++:not found  gcc:.rodata
const int a = 0x555555;//g++:not found  gcc:.rodata

void func1(int i)
{
        char * a ="abab";//.rodata
        const char c[] = "eeee";//.text(len >3)
        char b[] = "ddd";//.rodata(len <=3)
        char d[] = "xxxx";//.text(>3 ?)
        printf("%d/n",i);
}
int main()
{
        static int static_var = 85;//.data
        static int static_var2;

        int a = 1;
        int b;

        func1(static_var+static_var2 + a+b);
        return a;
}

经过objdump测试.o文件:

所有的初始化后的非const的全局变量变量或者局部static变量都放在.data段

而在g++下:

在gcc下:

参考:全局变量,静态变量以及局部变量存放位置
参考:
参考:

标签:面试题,变量,C语言,static,内存,进程,hello,备用
来源: https://blog.csdn.net/juluwangriyue/article/details/118500172