志在指尖
用双手敲打未来

c语言编辑器(为什么运行不了)

c语言编辑器

C言语算是大学里接触的最早,用的最”多”的言语了,关于大部分学习计算机的学生基本上是从开端学习C言语起,凭借着一句经典的”hello,world!”迈入了计算机的国际的,体会了一把这个国际还有个叫编程的活。作为体系级的开发首选言语,自诞生以来就屹立不倒,C言语的重要性是不言而喻的。做为一个菜鸟级别的程序员,运用C有些年,但关于C没有有真实的了解。我想有必要重新了解这门陈旧的言语背面的东西,知其然还要知其所以然,才能更好的运用这门言语。
关于C言语编写的HelloWorld程序(如下),关于程序员来说肯定如雷贯耳,便是这样一个简略的程序,你真的了解她吗?
#include
intmain()
{
printf(“HelloWorld\n”)
return0;
}
关于下面这些问题,你脑子里能够马上反映出一个清晰、显着的答案吗?
程序为什么要被编译器编译之后才能够运转?
编译器在把C言语程序转换成能够履行的机器码的进程中做了什么?怎样做的?
终究编译出来的可履行文件里边是什么?除了机器码还有什么?他们怎样寄存的?怎样安排的?
#include是什么意思?把stdio.h包含进来意味着什么?C言语库又是什么?它怎样完结的?
不同的编译器(MicrosoftVC、GCC)和不同的硬件平台(x86、SPARC、MIPS、ARM),以及不同的操作体系(Windows、Linux、UNIX、Solaris),终究编译出来的成果相同吗?为什么?
HelloWorld程序是怎样运转起来的?操作体系是怎样装载它的?他从哪里开端履行?到哪儿完毕?main函数之前发生了什么?main函数完毕之后又发生了什么?
假如没有操作体系,HelloWorld能够运转吗?假如要在一台没有操作体系的机器上运转HelloWorld需求什么?应该怎样完结?
printf是怎样完结的?他为什么能够有不定数量的参数?为什么它能够在终端上输出字符串?
HelloWorld程序在运转时,它在内存中是什么姿态的?
2.C程序编译流程
编译一个C程序能够分为四阶段:预处理阶段—>生成汇编代码阶段—>汇编阶段—>链接阶段。
这儿以linux环境下gcc编译器为例。直接运用gcc时,默许会直接完结以上四个进程然后生成能够履行的程序,但经过编译选项能够操控值进行某些阶段,检查中心的文件。
gcc指令的一般格局为(mangcc或者gcc-h检查更过选项协助):
gcc[选项]要编译的文件[选项][方针文件]其中,方针文件可缺省,gcc默许生成可履行的文件名为:a.outgccmain.c直接生成可履行文件a.outgcc-Emain.c-ohello.i生成预处理后的代码(仍是文本文件)gcc–Smain.c-ohello.s生成汇编代码gcc–cmain.c-ohello.o生成方针代码
C程序方针文件和可履行文件结构
方针文件和可履行文件能够有几种不同的格局,有ELF(ExcutableandlinkingFormat,可履行文件和链接)格局,也有COFF(CommonObject-FileFormat,一般方针文件格局)。
尽管格局不相同,但具有一个共同的概念,那便是段(segments),这儿段指二进制格局文件中的一块区域。
linux下的可履行文件有三个段:(可用nm指令检查方针文件的符号清单)
文本段(text)
数据段(data)
bss段
编译进程
源文件—–>到可履行文件。图引自《C专家编程》
注意:
BSS段,并没有保存未初始化段的映像,只是记载了该段的巨细(应为该段没有初值,不论具体值),到了运转时再到内存为未初始化变量分配空间,这样能够节省方针文件空间。
data段,只是保存在方针文件中,运转时直接载入。
C程序的内存布局
讲C言语内存办理的书本或者博客?:https://www.zhihu.com/question/29922211
readelf指令:http://man.linuxde.net/readelf
面试官问我:bss段的巨细记载在哪里?:http://bbs.csdn.net/topics/390613528
内存区区别、内存分配、常量存储区、堆、栈、自由存储区、大局区:http://www.cnblogs.com/CBDoctor/archive/2011/12/24/2300624.html
常量存在内存中的那里?:http://bbs.csdn.net/topics/390510503
运转进程
可履行文件—–>内存空间
不论是在Linux下C程序仍是Windows下C程序,他们都是由text段、data段、BSS段、堆(heap)、栈(stack)等段构成的,只不过或许他们的各段分配地址不相同。
Linux下的C程序正文段在低地址,而Windows下的C程序的正文段(代码段)在高地址。
所以不必担心Linux环境和Windows环境测验时得到不正确的数据。c语言
图示1:
图示2:
C言语存储空间的布局
C言语一直由下面部分组成:
正文段(codesegment/textsegment,.text段):或称代码段,通常是用来寄存程序履行代码的一块内存区域。这部分区域的巨细在程序运转前就现已确定,而且内存区域通常归于只读,某些架构也答应代码段为可写,即答应修改程序。在代码段中,也有或许包含一些只读的常数变量,例如字符串常量等。CPU履行的机器指令部分。(寄存函数体的二进制代码。)
只读数据段(ROdata,.rodata):只读数据段是程序运用的一些不会被改动的数据,运用这些数据的方法相似查表式的操作,因为这些变量不需求修改,因而只需放在只读存储器中。
已初始化读写数据段(datasegment,.data段):通常是用来寄存程序中已初始化的大局变量的一块内存区域。数据段归于静态内存分配。常量字符串便是放在这儿的,程序完毕后由体系开释(rodata—readonlydata)。已初始化读写数据段(RWdata,.data):已初始化数据是在程序中声明,而且具有初值的变量,这些变量需求占用存储器空间,在程序履行时它们需求坐落可读写的内存区域,并具有初值,以供程序读写。
*只读数据段和数据段统称为数据段
BSS段(bsssegment,.bss段):未初始化数据段(BSS,.bss)通常是指用来寄存程序中未初始化的大局变量的一块内存区域。BSS是英文BlockStartedbySymbol的简称。BSS段归于静态内存分配。大局变量和静态变量的存储是放在一块的。初始化的大局变量和静态变量在一块区域(.rwdataor.data),未初始化的大局变量和未初始化的静态变量在相邻的另一块区域(.bss),程序完毕后由体系开释。未初始化数据是在程序中声明,可是不具有初值的变量,这些变量在程序运转之前不需求占用存储空间。读取BSS段巨细,然后在内存中紧跟data段之后分配空间,而且清零(这也是为什么大局表量和static局部变量不初始化会有0值得原因)
*在C++中,现已不再严格区别bss和data了,它们同享一块内存区域
*静态存储区包含bbs段和data段
堆(heap):堆是用于寄存进程运转中被动态分配的内存段,它的巨细并不固定,可动态扩张或减缩。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数开释内存时,被开释的内存从堆上被除掉(堆被减缩)。一般由程序员分配开释(new/malloc/callocdelete/free),若程序员不开释,程序完毕时或许由OS收回。注意:它与数据结构中的堆是两回事,但分配方法倒相似于链表
栈(stack):栈又称仓库,是用户寄存程序临时创立的局部变量,也便是咱们函数大括号”{}”中界说的变量(不包含static声明的变量)。除此以外,在函数被调用时,其参数也会被压入建议调用的进程栈中,而且等调用完毕后,函数的回来值也会被寄存在回栈中。因为栈的先进先出特性,一切栈特别便利用来保存/恢复调用现场。从这个意义上讲,把仓库当作一个寄存、交换临时数据的内存区。由编译器主动分配开释,寄存函数的参数值,局部变量的值等。其操作方法相似于数据结构中的栈
上图是方针文件的典型结构,实践的情况或许会有所不同,但都是在这个基础上衍生出来的。
ELF文件头:即上图中的榜首个段。其中的header是方针文件的头部,里边包含了这个方针文件的一些基本信息。如该文件的版别、方针机器类型、程序进口地址等等。
文本段:里边的数据首要是程序中的代码部分。
数据段:程序中的数据部分,比方说变量。
重定位段:重定位段包含了文本重定位和数据重定位,里边包含了重定位信息。一般来说,代码中都会存在引证了外部的函数,或者变量的情况。既然是引证,那么这些函数、变量并没存在该方针文件内。在运用他们的时分,就要给出他们的实践地址(这个进程发生在链接的时分)。正是这些重定位表,供给了寻找这些实践地址的信息。理解了上面之后,文本重定位和数据重定位也就不难理解了。
符号表:符号表包含了源代码中一切的符号信息。包含每个变量名、函数名等等。里边记载了每个符号的信息,比方说代码中有“student”这个符号,对应的在符号表中就包含这个符号的信息。包含这个符号所在的段、它的特点(读写权限)等相关信息。其实符号表开始的来源能够说是在编译的词法分析阶段。在做词法分析的时分,就把代码中的每个符号及其特点都记载在符号表中。
字符串表:和符号表差不多的功用,寄存了一些字符串信息。
实践中的方针文件会比这个模型要杂乱些,可是它的思路都是相同的,便是依照类型来存储,再加上一些描述方针文件信息的段和链接中需求的信息。
具体验证能够参看(C言语存储空间布局以及static详解:http://blog.csdn.net/thanksgining/article/details/41960369)
程序和方针的对应关系
运用readelf和objdump解析方针文件(http://www.jianshu.com/p/863b279c941e)
inta=0;//a在data
char*p1;//p1在bss
main()
{
intb;//b在stack
chars[]=”abc”;//s在stack,abc\0在常量区
char*p2;//p2在stack
char*p3=”123456″;//p3在stack,123456\0在常量区
staticintc=0;//c在data
p1=(char*)malloc(10);//申请的10字节内存在heap,bss中的指针指向heap中的内存
p2=(char*)malloc(20);//申请的20字节内存在heap,stack中的指针指向heap中的内存
strcpy(p1,”123456″);//123456\0在常量区,编译器或许会将它与p3所指向的”123456\0″优化成一块
}
堆和栈的区别
办理方法:关于栈来讲,是由编译器主动办理;关于堆来说,开释作业由程序员操控,容易发生memoryleak。
空间巨细:一般来讲在32位体系下,堆内存能够到达挨近4G的空间,从这个角度来看堆内存几乎是没有什么约束的。可是关于栈来讲,一般都是有必定的空间巨细的,例如,在VC6下面,默许的栈空间巨细大约是1M。
碎片问题:关于堆来讲,频频的new/delete势必会构成内存空间的不接连,然后构成许多碎片,使程序功率降低;关于栈来讲,则不会存在这个问题,因为栈是先进后出的行列,永远都不或许有一个内存块从栈中心弹出。
成长方向:关于堆来讲,成长方向是向上的,也便是向着内存地址添加的方向;关于栈来讲,它的成长方向是向下的,是向着内存地址减小的方向添加。
分配方法:堆都是动态分配的,没有静态分配的堆;栈有2种分配方法:静态分配和动态分配。静态分配是编译器完结的,比方局部变量的分配,动态分配由alloca函数进行分配,可是栈的动态分配和堆是不同的,它的动态分配是由编译器进行开释,不需求咱们手工完结。
分配功率:栈是机器体系供给的数据结构,计算机会在底层分配专门的寄存器寄存栈的地址,压栈出栈都有专门的指令履行,这就决议了栈的功率比较高;堆则是C/C++函数库供给的,它的机制是很杂乱的,例如为了分配一块内存,库函数会依照必定的算法(具体的算法能够参阅数据结构/操作体系)在堆内存中查找可用的满足巨细的空间,假如没有满足巨细的空间(或许是因为内存碎片太多),就有或许调用体系功用去添加程序数据段的内存空间,然后进行回来。显着,堆的功率比栈要低得多。
无论是堆仍是栈,都要防止越界现象的发生。
关于Global和Static类型的一点评论
1.static大局变量与一般的大局变量有什么区别?
大局变量(外部变量)的界说前面再加上static就构成了静态的大局变量。
大局变量自身便是静态存储方法,静态大局变量当然也是静态存储方法。这两者在存储方法上并无不同。
这两者的区别在于非静态大局变量的效果域是整个源程序,当一个源程序由多个源文件组成时,非静态的大局变量在各个源文件中都是有用的。而静态大局变量则约束了其效果域,即只在界说该变量的源文件内有用,在同一源程序的其它源文件中不能运用它。
因为静态大局变量的效果域局限于一个源文件内,只能为该源文件内的函数共用,因而能够防止在其它源文件中引起错误。
static大局变量只初使化一次,防止在其他文件单元中被引证。
2.static局部变量和一般局部变量有什么区别?
把局部变量改动为静态变量后是改动了它的存储方法,即改动了它的生存期。把大局变量改动为静态变量后是改动了它的效果域,约束了它的运用范围。
static局部变量只被初始化一次,下一次根据上一次成果值。
3.static函数与一般函数有什么区别?
static函数与一般函数效果域不同:
static函数仅在本文件有用,只在当前源文件中运用的函数应该阐明为内部函数(static),内部函数应该在当前源文件中阐明和界说。
一般函数可在当前源文件以外运用。应该在一个头文件中阐明,要运用这些函数的源文件要包含这个头文件。
static函数在内存中只要一份(.data),一般函数在每个被调用中维持一份复制。
函数调用栈
作为面向进程的言语,C基本的特征便是模块化、进程化。一个C程序或一个模块由一堆函数组成,然后程序履行,按代码的结构调用这些函数,完结功用。那么函数调用的背面编译器究竟为咱们做了什么呢?
voidfun(inta,doubleb)
{
intc=300;
c+=1;
}
intmain()
{fun(100,200);return0;
}
.globl_fun;大局函数符号
.def_fun;_fun:;函数fun进口pushl%ebp;保存ebp值
movl%esp,%ebp;选用ebp来拜访栈顶
subl$4,%esp;esp用来扩展仓库分配局部变量空间
movl$300,-4(%ebp);局部变量赋值
leal-4(%ebp),%eax;得到局部变量有用地址
incl(%eax);拜访局部变量
leave;相当于movlebp,esppopebp
ret
.globl_main
.def_main;_main:;main函数进口
;….
movl$200,4(%esp);参数入栈
movl$100,(%esp);参数入栈
call_fun
;…..
函数调用进程
参数按从右到左次序放到栈顶上
call调用,将回来地址ip入栈保存
在栈上分配局部变量空间
履行函数操作
能够运用OD动态调试,就能够理解。。。
函数回来进程
ret会从栈上弹出回来地址
履行调用前后边的代码
由此得的结论是,函数调用一个动态的进程,调用的时分又有一个栈帧,调用的时分展开,完毕的时分缩短。局部变量在运转到该函数的时分在栈上分配内存,这些内存实践上没有姓名的,不同于数据段,有符号姓名,局部变量在函数完毕就销毁了。这也是什么局部变量同名互补干与的原因,因为编译今后,根本就不是经过姓名来拜访的。
大局变量
大局变量有初始化或未初始化之分:
初始化了的大局变量保存在data段,
未初始化大局变量保存在BSS段,
data段和BSS段都是程序的数据段
intglobal1=100;intmain(){global1=101;externintglobal2;global2=201;return0;}intglobal2=200;.globl_global1;大局符号global1.data;坐落数据段.align4_global1:.long100;大局变量初值;……globl_main;大局符号main.def_main;;是一个函数_main:;函数进口;…movl$101,_global1;经过符号拜访大局变量movl$201,_global2;经过符号拜访大局变量,这个变量还未界说movl$0,%eaxleaveret.globl_global2:大局符号golbal2.data;坐落数据段.align4_global2:;大局变量的界说,初始化值.long200intglobal1;intmain(){global1=101;externintglobal2;global2=201;return0;}intglobal2;.globl_main.def_main;_main:;….movl$101,_global1;经过符号拜访大局变量,这个符号能够在之后,或其他文件中界说movl$201,_global2movl$0,%eaxleaveret.comm_global1,16#4;标明这是个未初始化大局变量,声明多个,但终究运转时在bss段分配空间.comm_global2,16#4
能够得出结论:大局变量独立于函数存在,一切函数都能够经过符号拜访,而且在运转期,其地址不变。
编译与链接
看下面这个程序链接犯错,找不符号a、print,但生成汇编代码并没有问题。这是因为编译的时分只是把符号地址记载下来,比及链接的时分该符号界说了才会变成具体的地址。
假如链接的时分一切符号地址都有界说,那么生成可履行文件。假如有不确定地址的符号,则链接犯错。
#includeintmain()
{
externinta;print(“a=%d\n”,a);return0;
}
.file”fun.c”.def___main;
.section.rdata,”dr”LC0:
.ascii”a=%d\12\0″.text
.globl_main
.def_main;.
_main:
;..
movl_a,%eax;经过符号拜访大局变量a
movl%eax,4(%esp)
movl$LC0,(%esp)
call_print;经过符号拜访函数printmovl$0,%eax
leave
ret
.def_print;;阐明print是个函数符号
大局变量的链接特点
大局变量的默许是extern的,终究寄存在数据段,整个程序的一切文件都能拜访,假如加上static则表明值能被当前文件拜访。
#includestaticinta=10;intmain(){a=20;return0;}.data.align4_a:;大局变量a界说,少了glbal的声明.long10.def___main;.text.globl_main.def_main;_main:;…movl$20,_amovl$0,%eax去掉inta前面的static发生的汇编代码为:.globl_a;global声明符号a为大局.data.align4_a:.long10.def___main.text.globl_main.def_main_main:;…call__allocacall___mainmovl$20,_amovl$0,%eax关于未初始化大局变量#includestaticinta;intmain(){a=20;return0;}.globl_main.def_main;.scl2;.type32;.endef_main:;..movl$20,_amovl$0,%eaxleaveret.lcomm_a,16;多了个l表明是local的未初始化大局变量去掉inta前面的static.globl_main.def_main;.scl2;.type32;.endef_main:;..movl$20,_amovl$0,%eaxleaveret.comm_a,16#4;extern链接特点的未初始化大局变量
static局部变量
static局部变量具有外部变量的生存期,但效果域却和局部变量相同,离开函数就能拜访
#includeintfun()
{staticinta=10;return(++a);
}
intmain()
{
printf(“a=%d\n”,fun());printf(“a=%d\n”,fun());
}
.data.align4a.0:;static局部变量是放在代码段
.long10;分配空间初始化
.text
.globl_fun
.def_fun;_fun:pushl%ebp
movl%esp,%ebp
incla.0movla.0,%eax
popl%ebp
ret
.def___main;
.section.rdata,”dr”
编译实践仍是仍是把static局部变量放在数据段存储(要么怎样或许在程序运转期间地址不变呢),只不过符号名会动点手脚(这样出了函数就拜访不了了)。多个函数中界说同名的static局部变量,实践上是不同的内存单元,互补干与了。
3.a.out分析
a.out是方针文件的默许姓名。也便是说,当编译一个文件的时分,假如不对编译后的方针文件重命名,编译后就会发生一个姓名为a.out的文件。具体的为什么会用这个姓名这儿就不在深究了。有兴趣的能够自己google。咱们现在就来研究一下helloworld编译后构成的方针文件,这儿用C来描述。
简略的hellowworld源码:
class=”hljs-comment”>/*hello.c*/class=”hljs-meta”>#class=”hljs-meta-keyword”>includeclass=”hljs-meta-string”>class=”hljs-function”>class=”hljs-keyword”>intclass=”hljs-title”>mainclass=”hljs-params”>(){
class=”hljs-keyword”>inta=class=”hljs-number”>5;
class=”hljs-built_in”>printf(class=”hljs-string”>”helloworldn”);
class=”hljs-keyword”>returnclass=”hljs-number”>0;
}
为了能看清楚内部究竟是如何处理的,咱们运用GCC来编译。运转:gcchello.c再看咱们的目录下,就多了方针文件a.out。
现在咱们想做的是看看a.out里究竟有什么,或许有童鞋回想到用vim文本检查,当时我也是这么单纯的认为。但a.out是多么东西,怎能这么简略就暴露出来呢。是的,vim不行。“咱们遇到的问题大多是前人就现已遇到而且现已解决的”,对,其中有一个很强悍的东西叫做objdump。有了它,咱们就能完全的去了解方针文件的各种细节,当然还有一个叫做readelf也很有用,这个在后边介绍。这两个东西一般Linux里边都会自带有有,能够自行google
注:这儿的代码首要是在Linux下用GCC编译,检查方针文件用的是objdump、readelf
下面是a.out的安排结构:(每段的开始地址、、巨细等等)。检查方针文件的指令是objdump-ha.out
每一行都被分成了6列。从左到右:
榜首列(IdxName)是段的姓名,
第二列(Size)是巨细,
第三列VMA为虚拟地址,
第四列LMA为物理地址,
第五列Fileoff是文件内的偏移。也便是这段相关于段中某一参阅(一般是段开始)的间隔。
第六列Algn是对段特点的阐明,暂时不必理睬
段:
text段:代码段。
data段:也便是上面说的数据段,保存了源代码中的数据,一般是以初始化的数据。
bss段:也是数据段,寄存那些未初始化的数据,因为这些数据还未分配空间,所以单独寄存。
rodata段:只读数据段,里边寄存的数据是只读的。
cmment寄存的是编译器版别信息。
剩余的两段对咱们的评论没有实践意义,就不再介绍。认为他们包含了一些链接、编译、装在的信息就可。
注:这儿的方针文件格局只是列出实践情况中首要部分。实践情况还有一些表未列出。假如你也在用Linux,能够用objdump-X列出更具体的段内容。
检查a.out的段
上面经过实例说了方针文件中的典型的段,首要是段的信息,如:巨细等相关的特点。那么这些段里边究竟有些什么东西呢?”text段”里究竟存了什么东西?
仍是用objdump来检查下。objdump-sa.out经过-s选项就能够检查方针文件的十六进制格局。
检查成果如下:
如上图所示,列出了各段的十六进制表示方式。能够看出图中共分为两栏,
最左面:十六进制地址,
中心:十六进制数据
最右边:十六进制数据对应的ASCII码
比较显着的如”rodata”只读数据段中就有”helloworld”。
“comment”上文中说的这个段包含了一些编译器的版别信息,这个段后边的内容便是了:GCC编译器,后边的是版别号。
a.out反汇编
编译的进程总是先把源文先变为汇编方式,再翻译为机器言语。下面看下a.out的汇编
objdump-da.out能够列出文件的汇编:
不过这儿只列出了首要部分,即main函数部分,其实在main函数履行的开端和main函数履行今后,都还有多作业要做。即初始化函数履行环境以及开释函数占用的空间等。
a.out头文件
在介绍方针文件格局的时分,提到过头文件这个概念,里边包含了这个方针文件的一些基本信息。如该文件的版别、方针机器类型、程序进口地址等等。
下图是文件头的方式:readelf-ha.out
(图中检查的是hello.o,它是源文件hello.c编译但未链接的文件。这个和检查a.out大部分是相同的)
图中分为两栏,
左面一栏表示的是特点,
右边是特点值。
榜首行常被称为魔数。后边是一连串的数字,其中的具体意义就不多说了,能够自己去google。
对链接的简略知道
链接通俗的说便是把几个可履行文件进行组装。
假如程序A中引证了文件B中界说的函数,为了A中的函数能正常履行,就需求把B中的函数部分也放在A的源代码中,那么将A和B合并成一个文件的进程便是链接了。
有专门的进程用来链接程序,称为链接器。他将一些输入的方针文件加工后组成一个输出文件。这些方针文件中往往有相互的数据、函数引证。
上面的helloworld的反汇编方式,是一个还没有经过链接的文件,也便是说当引证外部函数的时分是不知道其地址的,如下图:
上图中,cal指令便是调用了printf()函数,因为这时分printf()函数并不在这个文件中,所以无法确定它的地址,在十六进制中就用“ffffff”来表示它的地址。等经过链接今后,这个地址就会变为函数的实践地址,应为衔接后这个函数现已被加载进入这个文件中了。
链接的分类:按把A相关的数据或函数合并为一个文件的先后能够把链接分为静态链接和动态链接。
静态链接:
在程序履行之前就完结链接作业。也便是等链接完结后文件才能履行。可是这有一个显着的缺点,比方说库函数。假如文件A和文件B都需求用到某个库函数,链接完结后他们衔接后的文件中都有这个库函数。当A和B同时履行时,内存中就存在该库函数的两份复制,这无疑糟蹋了存储空间。当规模扩展的时分,这种糟蹋尤为显着。静态链接还有不容易升级等缺点。为了解决这些问题,现在的许多程序都用动态链接。
动态链接:
和静态链接不相同,动态链接是在程序履行的时分才进行链接。也便是当程序加载履行的时分。仍是上面的比如,假如A和B都用到了库函数Fun(),A和B履行的时分内存中就只需求有Fun()的一个复制。
对装载的简略解释
咱们知道,程序要运转是必定要把程序加载到内存中的。
在曩昔的机器里都是把整个程序都加载进入物理内存中,
现在一般都选用了虚拟存储机制,即每个进程都有完整的地址空间,给人的感觉如同每个进程都能运用完结的内存。然后由一个内存办理器把虚拟地址映射到实践的物理内存地址。
依照上文的叙述,程序的地址能够分为虚拟地址和实践地址。
虚拟地址即她在她的虚拟内存空间中的地址,
物理地址便是她被加载的实践地址。
在上文中检查段的时分或许你现已注意到了,因为文件是未链接、未加载的,所以每个段的虚拟地址和物理地址都是0。
加载的进程能够这样理解:先为程序中的各部分分配好虚拟地址,然后再树立虚拟地址到物理地址的映射。其实关键的部分便是虚拟地址到物理地址的映射进程。程序装在完结之后,cpu的程序计数器pc就指向文件中的代码开始方位,然后程序就按次序履行。

未经允许不得转载:IT技术网站 » c语言编辑器(为什么运行不了)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载