程序内存管理 20131006

一个程序在运行期间的内存是如何的对编写程序至关重要,之前整理的C++内存管理的知识和Java程序内存管理的知识。今天我们系统的整理一下程序的内存。

1.一个程序的内存有BSS segment, data segment, code segment, heap, stack.

BSS Segment:通常是指用来存放程序中未初始化的全局的一块内存区域。BSS: Block Started by Symbol的简称,BSS内存分配是属于静态内存分配。

Data Segment: 通常知识的是存放程序中已经初始化的全局变量,数据段也是静态内存分配,存放初始化的全局变量和惊天变量,常量。

Code Segment: 用于存放程序执行代码的一块内存区域,这部分区域在程序运行之前就已经确定,并且这一部分的内存区域是只读的,但是也有一些架构允许代码段为可写的,即允许修改程序。代码段中,也可能包含一些只读的常量变量,如字符串常量等等。

Heap: 用于存放程序运行中被动态分配的内存,他的大小不固定,可以动态的扩张和缩减。当进程调用malloc等函数分配内顿的时候,新的内存空间就被动态的添加到heap中;当使用free等释放内存空间的时候,被释放的内存从堆中删除。

Stack: 又被称为堆栈,存储用户程序中的局部变量,但是不包含static声明的变量,static意味着数据存放在数据段。等到超出作用域的时候,自动清退栈中的数据。

文字常量区:字符串常量,编译阶段确定,运行期间是不会更改或者添加,同时是有操作系统维护和回收的。

参考一段代码:

代码段1:

int arr[10];

void main(){…}

代码段2:

int arr[10] = {1,2,3,4,5,6};

void main(){…}

代码2编译的exe文件时比代码段1要大的多:全局变量,如果没有被初始化,那么具体体现为一个占位符,存储在BSS段,同时BSS段是不占用exe文件的空间,其内容有操作系统初始化(清零);但是初始化的全局变量存储的区域是数据段,数据段是要占用exe文件的,内容由程序初始化。

代码3.

#include <stdio.h>

#define LEN 100000

int inbss[LEN] ;

float fA;

int indata[LEN] = {1,2,3,4,5,6};

double dbB = 100.0;

int main(void){

int run[100] = {1,2,3,4,5,6,7,8};

for(int i= 0 ; i < LEN;++i){

printf(“%d ”, inbss[i]);

}

return 0;

}

inbss [LEN] 未初始化的全局变量是位于BSS段的,indata是初始化的全局变量,位于数据段的。在bss段的数据知识占位符,变异的时候没有给他分配空间,只是记录数据所需要的空间的大小;但是在data段的数据在编译期间需要分配内存空间,数据保存在目标文件中。

数据段包含的初始化的全局变量的值,BSS段的大小可以从后面的可执行文件中得到,然后连接器会得到这个大小的内存空间,紧跟在数据段后面。当这个内存区进入程序的地址空间之后,全部清零,包含数据段和BSS段,统一称为数据区。

2.禁止产生堆中的对象

#include <iostream>

using namespace std;

class Test{

private:

int a;

void* operator new (unsigned size){

return malloc(size);

}

void operator delete(void * pp){

free(pp);

}

public:

Test(int a){

this->a= a;

}

int getA() {

return this->a;

}

void setA(int a){

this->a = a;

}

~Test(){

}

};

int main()

{

Test t(12);

cout << t.getA() << endl;

/*

这样就不允许创建在堆中的对象,因为我们重载了new 和delete ,并且声明是 private权限,在外部是不可以访问的

Test t = new Test(12); error,

但是同样是防君子不防小人,可以迂回的方式,先声明一个堆中的内存空间,是该class的大小,

然后将指针强制转换成Class Pointer即可,但是对于Class内部的数据需要我们自己动态的初始化,比如class内部

可能存在指针数据,那么我们自己需要设置value。同时对于对象可能会用到继承关系,如果使用了多态的话,

在对象中有一个地址就是虚表的地址,需要我们自己设置这一块内存的地址

*/

char * temp = new char[sizeof(Test)];

Test * pT = (Test*)temp;

temp = NULL;

pT->setA(100);

cout << pT->getA() << endl;

return 0;

}

3.禁止产生栈对象

其实在堆中声明一个对象的时候,new就是寻找一块地址空间的,但是在栈中是没有必要的。在栈中创建对象的时候,直接移动栈指针一定的大小,即对象的大小,然后调用对象的构造函数创建对象。当函数结束的时候直接调用对象的析构函数,释放对象,在调用栈指针回收内存空间。当我们在class中是构造函数和析构函数为私有的话,那么就不可以生成栈中的对象了。

但是我们也不能够使用new创建堆对象了,这种方法是稍微不完善的,所以我们还需要重载new 和delete 或者我们采用另一种方式产生对对象,但是这种不合适,会造成循环:就是使用一个静态函数创建一个堆对象,同时注意如何将对象释放掉。使用一个public函数吧,调用delete this

class Test{

protected:

int a;

Test(int a){

this->a= a;

}

~Test(){

cout << "~Test()" << endl;

}

public:

void destroy(){

delete this;

}

static Test* getHeapObj(int a){

return new Test(a);

}

int getA() {

return this->a;

}

void setA(int a){

this->a = a;

}

};

int main()

{

Test *pT = Test::getHeapObj(19);

cout << pT->getA() << endl;

pT->destroy();

return 0;

}

追梦的飞飞

于广州中山大学 20131006

HomePage: http://yangtengfei.duapp.com

C++复习12.程序内存管理的更多相关文章

  1. Java复习2.程序内存管理

    前言: 国庆节的第三天,大家都回家了,一个人在宿舍好无聊.不过这年头与其说是出去玩不如是说出去挤,所以在学校里还是清闲的好.找工作不用担心了,到时候看着你们慢慢忙:插个话题,大学都没有恋爱过,总之各种 ...

  2. C程序内存管理

    C程序的内存管理 熟悉Java语言的肯定知道,Java中内存管理是由虚拟机帮助我们完毕的,在C/C++中可不是这样,程序猿须要自己去分配和回收内存空间.本文记录了C程序可运行文件的存储结构.在内存中的 ...

  3. 笔记:程序内存管理 .bss .data .rodata .text stack heap

    1.未初始化的全局变量(.bss段) bss段用来存放 没有被初始化 和 已经被初始化为0 的全局变量.如下例代码: #include<stdio.h> int bss_array[102 ...

  4. C++中的内存管理

    在C++中也是少不了对内存的管理,在C++中只要有new的地方,在写代码的时候都要想着delete. new分配的时堆内存,在函数结束的时候不会自动释放,如果不delete我分配的堆内存,则会造成内存 ...

  5. Android 内存管理(二)

    很多开发者都是从j2me或j2ee上过来的,对于内存的使用和理解并不是很到位,Android开发网本次给大家一些架构上的指导,防止出现豆腐渣工 程的出现.Android作为以Java语言为主的智能平台 ...

  6. iOS内存管理策略和实践

    转:http://www.cocoachina.com/applenews/devnews/2013/1126/7418.html 内存管理策略(memory Management Policy) N ...

  7. [转载]Java应用程序中的内存泄漏及内存管理

    近期发现测试的项目中有JAVA内存泄露的现象.虽然JAVA有垃圾回收的机制,但是如果不及时释放引用就会发生内存泄露现象.在实际工作中我们使用Jprofiler调用java自带的 jmap来做检测还是很 ...

  8. 黑马程序员_ Objective-c 内存管理笔记

    引用计数器 当一个对象被创建出来,就要分配给内存这个对象,当不用这个对象的时候,就要及时的回收,为了可以明确知道对象有没有被使用,就要用引用计数器来体现,只要计数器不为0,表明对象被使用中. 1.方法 ...

  9. 程序员必读:Linux内存管理剖析

    现在的服务器大部分都是运行在Linux上面的,所以作为一个程序员有必要简单地了解一下系统是如何运行的. 对于内存部分需要知道: 地址映射 内存管理的方式 缺页异常 先来看一些基本的知识,在进程看来,内 ...

随机推荐

  1. Java设计模式—单例模式

    Singleton是一种创建型模式,指某个类采用Singleton模式,则在这个类被创建后,只可能产生一个实例供外部访问,并且提供一个全局的访问点. 核心知识点如下: (1) 将采用单例设计模式的类的 ...

  2. $digest / $apply digest in progress报错

    有的时候出于某种原因,如jq操作了model.或者$watch.setTimeout等函数改变了model,导致最后没有脏数据检测.所以我没就手动调用了$apply( )等.但是第一次运行的时候ang ...

  3. 设置eclipse编码格式

    1.修改eclipse默认工作空间编码方式.点击Window-->Preferences-->General-->Workspace,设置编码格式为UTF-8,然后点击OK.

  4. Java学习第四周学习笔记

    20145307<Java程序设计>第4周学习总结 教材学习内容总结 继承与多态 继承 继承作为面向对象的第二大特征,基本上就是避免多个类间重复定义共同行为.即当多个类中存在相同属性和行为 ...

  5. 0ctf2017-pages-choices

    Pages 题目来自于CCS 2016 <Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR>,利用intel pr ...

  6. MR案例:小文件处理方案

    HDFS被设计来存储大文件,而有时候会有大量的小文件生成,造成NameNode资源的浪费,同时也影响MapReduce的处理效率.有哪些方案可以合并这些小文件,或者提高处理小文件的效率呢? 1). 所 ...

  7. fatal: refusing to merge unrelated histories的解决方案

    最近更新了git版本,发现在github上建立了一个仓库,然后关联本地库的时候pull失败,错误为fatal: refusing to merge unrelated histories,查找后找到了 ...

  8. centos7更改主机名

    操作环境 [root@centos701 ~]# uname Linux [root@centos701 ~]# uname -a Linux centos701 3.10.0-693.el7.x86 ...

  9. cmd中如何查看环境变量

    查看所有环境变量 set 查看某一个环境变量 C:\WINDOWS\system32>set no_proxyNO_PROXY=localhost,127.0.0.1,172.31.212.14 ...

  10. Docker Mysql主主同步配置搭建Demo

    主主同步配置和主从配置很相似,仅需稍做修改就可以了,对主从配置有疑问可以查看 上一篇文章. 进行Docker操作前,先建立目录,我的路径是d:/docker/mysql,目录结构如下: --mysql ...