C++复习12.程序内存管理

news/2025/2/23 15:30:01

程序内存管理 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

转载于:https://www.cnblogs.com/hbhzsysutengfei/p/3409465.html

文章来源:https://blog.csdn.net/weixin_33971130/article/details/93829603
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.niftyadmin.cn/n/1279909.html

相关文章

mysql to days 索引_高性能mysql优化二之索引篇

前言为什么要使用索引&#xff1f;索引有什么用途呢&#xff1f;我的亲身经历&#xff0c;一个几千万数据的项目&#xff0c;我写了一条查询&#xff0c;没有用到索引&#xff0c;由于访问量比较大&#xff0c;瞬间网站就跪了&#xff0c;从此以后我写的每一条sql都会explain解…

位图和SVG用法比较

位图&#xff0c;亦称为点阵图像或绘制图像&#xff0c;是由称作像素&#xff08;图片元素&#xff09;的单个点组成的。这些点可以进行不同的排列和染色以构成图样。当放大位图时&#xff0c;可以看见赖以构成整个图像的无数单个方块。扩大位图尺寸的效果是增大单个像素&#…

STL容器的删除操作

今天做一个小程序&#xff0c;居然发现用vector的删除操作时遇到了问题&#xff1a;考虑&#xff0c;当需要遍历容器&#xff0c;并且对其中某些元素进行删除操作&#xff0c;正确的做法是怎样&#xff1f; 首先&#xff0c;容器的删除操作&#xff0c;如vector的erase&#xf…

PHP-操作数据库数据

1.3 操作数据 1.3.1 数据操作语句 通过mysqli_query()执行SQL语句 增、删、改语句执行成功返回true&#xff0c;失败返回false <?php //1、连接数据库 $linkmysqli_connect(localhost,root,root,data); //2、设置支付编码 mysqli_set_charset($link,utf8); //3、执行SQ…

php vs java性能分析工具_jemete(java apache) 压力测试工具 (接口测试工具) window apache php 环境...

近来笔者写了翻牌抽奖游戏为了测试中奖几率 笔者需要将抽奖接口跑大约2W的中奖记录PHP 使用for 循环也可以跑 但是效率却不敢恭维这个时候就需要我们使用工具来跑接口数据 (需要安装1、Java.jdk 2、jemete)jemete 简介&#xff1a;Apache JMeter是Apache组织开发的基于Java…

SQLPROMPT5.3对各种加密对象的解密测试

SQLPROMPT5.3对各种加密对象的解密测试 测试环境&#xff1a; SQL2005个人开发者版 SP4 SQLPROMPT版本&#xff1a;5.3.8.2 视图 1 CREATE VIEW aa 2 WITH ENCRYPTION 3 AS 4 SELECT * FROM [dbo].[Users] 可以解密 存储过程 1 CREATE PROCEDURE bb 2 WITH ENCRYPTION 3 AS 4 S…

PHP-实战新闻模块

1.4 新闻模块 1.4.1 包含文件 由于所有的操作都要连接数据库&#xff0c;将连接数据库的代码存放到包含文件中 步骤 1、在站点下创建inc文件夹 2、在inc下创建conn.php文件&#xff0c;用来连接数据库&#xff0c;代码就是上面连接数据库的代码 代码实现 <?php //连…

python风变编程知乎_如何看待风变编程的 Python 网课?

来自一位32岁风变上班族学员&#xff1a;起初是工作午休的时候&#xff0c;收到了风变的推送&#xff0c;觉得Python周围同事就有在使用的&#xff0c;自己也是很好奇。自身最早接触编程还停留在大学时候学的Turbo C&#xff0c;后来换了工作略微接触到点C#代码&#xff0c;工作…