关于书上说的“编译的时候分配内存”
2017-09-22 00:00
281 查看
一下均为网络上收集的资料:
1、所谓在编译期间分配空间指的是静态分配空间(相对于用new动态申请空间),如全局变量或静态变量(包括一些复杂类型的常量),它们所需要的空间大小可以 明确计算出来,并且不会再改变,因此它们可以直接存放在可执行文件的特定的节里(而且包含初始化的值),程序运行时也是直接将这个节加载到特定的段中,不 必在程序运行期间用额外的代码来产生这些变量。
其实在运行期间再看“变量”这个概念就不再具备编译期间那么多的属性了(诸如名称,类型,作用域,生存期等等),对应的只是一块内存(只有首址和大小), 所以在运行期间动态申请的空间,是需要额外的代码维护,以确保不同变量不会混用内存。比如写new表示有一块内存已经被占用了,其它变量就不能再用它了; 写delete表示这块内存自由了,可以被其它变量使用了。(通常我们都是通过变量来使用内存的,就编码而言变量是给内存块起了个名字,用以区分彼此)
内存申请和释放时机很重要,过早会丢失数据,过迟会耗费内存。特定情况下编译器可以帮我们完成这项复杂的工作(增加额外的代码维护内存空间,实现申请和释 放)。从这个意义上讲,局部自动变量也是由编译器负责分配空间的。进一步讲,内存管理用到了我们常常挂在嘴边的堆和栈这两种数据结构。
最后对于“编译器分配空间”这种不严谨的说法,你可以理解成编译期间它为你规划好了这些变量的内存使用方案,这个方案写到可执行文件里面了(该文件中包含若干并非出自你大脑衍生的代码),直到程序运行时才真正拿出来执行。
2、编译其实只是一个扫描过程,进行词法语法检查,代码优化而已,编译程序越好,程序运行的时候越高效。 我想你说的“编译时分配内存”是指“编译时赋初值”,它只是形成一个文本,检查无错误,并没有分配内存空间。
当你运行时,系统才把程序导入内存。一个进程(即运行中的程序)在主要包括以下五个分区: 栈、堆、bss、data、code
代码(编译后的二进制代码)放在code区,代码中生成的各种变量、常量按不同类型分别存放在其它四个区。系统依照代码顺序执行,然后依照代码方案改变或调用数据,这就是一个程序的运行过程。
3、
编译时分配内存 --------------- 编译时是不分配内存的。此时只是根据声明时的类型进行占位,到以后程序执行时分配内存才会正确。所以声明是给编译器看的,聪明的编译器能根据声明帮你识别错误。
运行时分配内存 --------------- 这是对的,运行时程序是必须调到“内存”的。因为CPU(其中有多个寄存器)只与内存打交道的。程序在进入实际内存之前要首先分配物理内存。
编译过程 -------------- 只能简单说一下,因为如果要详细的话,就是一本书了《编译原理》。编译器能够识别语法,数据类型等等。然后逐行逐句检查编译成二进制数据的obj文件,然后再由链接程序将其链接成一个EXE文件。此时的程序是以EXE文件的形式存放在磁盘上。
运行过程 -------------- 当执行这个EXE文件以后,此程序就被加载到内存中,成为进程。此时一开始程序会初始化一些全局对象,然后找到入口函数(main()或者WinMain()),就开始按程序的执行语句开始执行。此时需要的内存只能在程序的堆上进行动态增加/释放了。
int a =0; //全局初始化区
char*p1; //全局未初始化区
int main() {
int b; //栈
char s[] = \"abc\"; //栈
char*p2; //栈
char*p3 = \"123456\"; //123456\\0在常量区,p3在栈上。
staticint c =0;//全局(静态)初始化区
p1 =newchar[10];
p2 =newchar[20];
//分配得来得和字节的区域就在堆区。
strcpy(p1, \"123456\"); //123456\\0放在常量区,编译器可能会将它与p3所指向的\"123456\"优化成一个地方。
}
1、所谓在编译期间分配空间指的是静态分配空间(相对于用new动态申请空间),如全局变量或静态变量(包括一些复杂类型的常量),它们所需要的空间大小可以 明确计算出来,并且不会再改变,因此它们可以直接存放在可执行文件的特定的节里(而且包含初始化的值),程序运行时也是直接将这个节加载到特定的段中,不 必在程序运行期间用额外的代码来产生这些变量。
其实在运行期间再看“变量”这个概念就不再具备编译期间那么多的属性了(诸如名称,类型,作用域,生存期等等),对应的只是一块内存(只有首址和大小), 所以在运行期间动态申请的空间,是需要额外的代码维护,以确保不同变量不会混用内存。比如写new表示有一块内存已经被占用了,其它变量就不能再用它了; 写delete表示这块内存自由了,可以被其它变量使用了。(通常我们都是通过变量来使用内存的,就编码而言变量是给内存块起了个名字,用以区分彼此)
内存申请和释放时机很重要,过早会丢失数据,过迟会耗费内存。特定情况下编译器可以帮我们完成这项复杂的工作(增加额外的代码维护内存空间,实现申请和释 放)。从这个意义上讲,局部自动变量也是由编译器负责分配空间的。进一步讲,内存管理用到了我们常常挂在嘴边的堆和栈这两种数据结构。
最后对于“编译器分配空间”这种不严谨的说法,你可以理解成编译期间它为你规划好了这些变量的内存使用方案,这个方案写到可执行文件里面了(该文件中包含若干并非出自你大脑衍生的代码),直到程序运行时才真正拿出来执行。
2、编译其实只是一个扫描过程,进行词法语法检查,代码优化而已,编译程序越好,程序运行的时候越高效。 我想你说的“编译时分配内存”是指“编译时赋初值”,它只是形成一个文本,检查无错误,并没有分配内存空间。
当你运行时,系统才把程序导入内存。一个进程(即运行中的程序)在主要包括以下五个分区: 栈、堆、bss、data、code
代码(编译后的二进制代码)放在code区,代码中生成的各种变量、常量按不同类型分别存放在其它四个区。系统依照代码顺序执行,然后依照代码方案改变或调用数据,这就是一个程序的运行过程。
3、
编译时分配内存 --------------- 编译时是不分配内存的。此时只是根据声明时的类型进行占位,到以后程序执行时分配内存才会正确。所以声明是给编译器看的,聪明的编译器能根据声明帮你识别错误。
运行时分配内存 --------------- 这是对的,运行时程序是必须调到“内存”的。因为CPU(其中有多个寄存器)只与内存打交道的。程序在进入实际内存之前要首先分配物理内存。
编译过程 -------------- 只能简单说一下,因为如果要详细的话,就是一本书了《编译原理》。编译器能够识别语法,数据类型等等。然后逐行逐句检查编译成二进制数据的obj文件,然后再由链接程序将其链接成一个EXE文件。此时的程序是以EXE文件的形式存放在磁盘上。
运行过程 -------------- 当执行这个EXE文件以后,此程序就被加载到内存中,成为进程。此时一开始程序会初始化一些全局对象,然后找到入口函数(main()或者WinMain()),就开始按程序的执行语句开始执行。此时需要的内存只能在程序的堆上进行动态增加/释放了。
int a =0; //全局初始化区
char*p1; //全局未初始化区
int main() {
int b; //栈
char s[] = \"abc\"; //栈
char*p2; //栈
char*p3 = \"123456\"; //123456\\0在常量区,p3在栈上。
staticint c =0;//全局(静态)初始化区
p1 =newchar[10];
p2 =newchar[20];
//分配得来得和字节的区域就在堆区。
strcpy(p1, \"123456\"); //123456\\0放在常量区,编译器可能会将它与p3所指向的\"123456\"优化成一个地方。
}
相关文章推荐
- 转-关于书上说的“编译的时候分配内存”
- 关于书上说的“编译的时候分配内存”
- 关于书上说的“编译的时候分配内存”
- C++ 关于书上说的“编译的时候分配内存”
- 关于书上说的“编译的时候分配内存”
- 关于创建子类对象的时候是否为父类的私有变量分配了内存
- OO 中的继承分析:主要分析在编译和运行过程中 子类、父类 的字段和方法以及实例化时候在内存中分配 和 执行的先后,以及两个原则
- OO中的继承分析,主要分析在编译和运行过程中子类父类的方法、字段和实例化时候在内存中分配和执行的先后,以及两个原则
- 关于VS编译的程序内存分配只能用1.5~2G上限的优化方案
- 1.22关于new动作的分析(编译时加载类信息,运行时分配内存)
- 当数组元素是应用类型的时候,关于内存分配的理解误区
- 关于VS编译的程序内存分配只能用1.5~2G上限的优化方案
- 编译到执行 关于内存分配
- 关于类静态成员变量指针通过动态分配的内存如何回收的探讨
- 关于我写的strcpy的延伸出的问题——程序运行时内存的分配
- 关于内存分配(包括堆/栈)的问题
- 关于linux的内存分配
- /Zm(指定预编译头的内存分配限制)
- 内存分配的问题:关于malloc与free
- 关于内存分配的一点小知识