c++动态内存管理题目

malloc/free和new/delete的区别

malloc/freenew/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:

  1. mallocfree是函数,newdelete是操作符
  2. malloc申请的空间不会初始化,new可以初始化
  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可
  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
  7. new/delete比malloc和free的效率稍微低点,因为new/delete的底层封装了malloc/free

请设计一个类,该类只能在堆上创建对象

  1. 构造函数私有化
  • 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。
  • 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建
class HeapOnly   {     public:         static HeapOnly* CreateObject()     {             return new HeapOnly;       } private:       HeapOnly() {}        // C++98    // 1.只声明,不实现。因为实现可能会很麻烦,而你本身不需要    // 2.声明成私有    HeapOnly(const HeapOnly&)}
  1. c++11中提供delete
 HeapOnly(const HeapOnly&) = delete; 

请设计一个类,该类不能在栈上创建对象

class StackOnly   
{    
public:        static StackOnly CreateObject()      {             return StackOnly();      } private:   StackOnly()  {} 
}; 

只能在栈上创建对象,即不能在堆上创建

因此只要将new的功能屏蔽掉即可,即屏蔽掉operator new和定 位new表达式,注意:屏蔽了operator new,实际也将定位new屏蔽掉。

class StackOnly    
{    
public:       StackOnly()  {} private:        void* operator new(size_t size);    void operator delete(void* p); }; 

检测下面程序运行结果

class Test
{
public:~Test(){delete this;}};int main()
{Test* pt = new Test;delete pt;return 0;
}

答:无限递归,每回在释放对象时delete thisthis又是对象,又要调用析构,所以无限递归。

如何一次在堆上申请4G的内存?

在探讨这个问题之前,我们需要认识到机器的内存分布。
因为Windows下的机器内存分布模型我们不清楚。所以我们在这里讨论的是Linux下的4G内存空间的申请。

假如我们现在的Linux一共有4G的内存空间。那么它有1G是供操作系统内核使用的。也就是说我们程序最多只能申请到3G的空间,事实上,我们最大申请到的空间也就2G左右。

#include<iostream>
using namespace std;
int main()
{void* p = new char[0xfffffffful];cout << "new:" << p << endl;return 0;}

上述代码按64位编译就可以申请了

不要疑问4G*4G空间,我们知道虚拟地址空间和物理地址空间之间有一种映射关系,我们能申请到并不意味着物理地址真的有这么大。你想,我们申请到的4G空间并不是说需要一下子需要这么大,只是说可以满足我们4G的需求就可以了,所以当你用到的地方才会真的申请空间,一旦哪一部分释放空间了,就会把前边释放的空间再拿过来用(读者可以想象这个过程)。

内存泄露

什么是内存泄露

内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上 的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪 费。

内存泄露分类

  • 堆内存泄露
    堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存, 用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那 么以后这部分空间将无法再被使用,就会产生Heap Leak
  • 系统资源泄漏
    指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统 资源的浪费,严重可导致系统效能减少,系统执行不稳定。

如何解决

  1. Linux下有相应的工具进行检测
  2. windows下有第三方工具进行检测
  3. 其他工具

如何避免

  1. 事前预防,如c++中智能指针
  2. 事后查错,如检错工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383138.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

私人博客定制----封装数据库接口

封装MySQLAPI 我们先把初始化句柄和断开句柄进行一个封装 static MYSQL* MySQLInit(){ //1.初始化一个Mysql句柄建立连接 MYSQL* connect_fd mysql_init(NULL); //2.和数据库建立连接 if (mysql_real_connect(connect_fd, "127.0.0.1", "root&quo…

私人博客定制---服务器接口封装

实现服务器接口 我们用一个http服务器作为底层&#xff0c;但是c中并没有先成的http服务器&#xff0c;所以我在GitHub上找到一个牛人写的http服务器&#xff0c;拿来直接用&#xff0c;节省本项目开发的时间 这是服务器的链接地址 上面有详细的使用方法&#xff0c;本文就不再…

私人博客定制

项目背景 可行性方面 需求分析&#xff1a; 详细设计&#xff1a; 数据库设计 博客管理API的设计 标签相关API 服务器端的实现 对数据库操作进行封装 对服务器操作进行封装 客户端实现 具体操作 使用markdown 具体实现 测试 项目效果展示 维护 完整代码 项目…

初识c++中的函数模板

函数模板 函数模板概念 函数模板:编译器生成代码的一个规则。函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型产生函数的特定类型版本。 函数模板格式 //要让这个函数与类型无关 //Add函数模板 template…

深入理解c++中的函数模板

非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可将该参数当成常量来使…

c++中的IO流

c语言中的IO操作 标准类型的输入输出: 输入------>数据来源是通过键盘进行输入输出------>程序中的数据输出到控制台 c语言中: scanf:输入 printf:输出 两个函数的相同点 1 —格式串 2 —不定参数 两个函数的缺陷 1 —用户要提供数据的格式—用户要记忆大量的格式串—…

201301 JAVA2~3级---走格子

请编写一个函数&#xff08;允许增加子函数&#xff09;&#xff0c;计算n x m的棋盘格子&#xff08;n为横向的格子数&#xff0c;m为竖向的格子数&#xff09;沿着各自边缘线从左上角走到右下角&#xff0c;总共有多少种走法&#xff0c;要求不能走回头路&#xff0c;即&…

复习Linux基本操作----常见指令

Linux基本操作 ls命令 ls(list):相当于windows上的文件资源管理器 语法&#xff1a; ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目…

复习Linux基础操作---权限操作

shell命令以及运行原理 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#xff0c;来与kernel沟…

【剑指offer】_01 (二维数组中的查找)

题目描述 在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该…

【剑指offer】_02替换空格

题目描述 请实现一个函数&#xff0c;将一个字符串中的每个空格替换成“%20”。例如&#xff0c;当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 解题思路 首先我们先算出整个字符串的长度&#xff0c;还有总共多少个空格。因为空格只占一个字节&#…

【剑指offer】_04 重建二叉树

题目描述 输入某二叉树的前序遍历和中序遍历的结果&#xff0c;请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}&#xff0c;则重建二叉树并返回。 解题思路 用前序的顺序…

再谈c++中的多态

何为多态 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 多态的实现 在继承的体系下 基类中必须有虚函数(被virtual关键字修饰的成员函数)&#xff0c;在派生类中必须…

再谈c++中的继承

继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序设计的层次结构&#xff0c;体现了…

红黑树概念及其相关操作的实现

红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但它并不像AVL树一样&#xff0c;每个结点绑定一个平衡因子。但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过 对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c…

模拟实现STL中map和set容器

红黑树的迭代器 //红黑树的迭代器 template<class T> struct RBTreeIterator {typedef RBTreeNode<T>Node;typedef RBTreeIterator<T> Self; public:RBTreeIterator(Node* pNode nullptr):_pNode(pNode){}//具有指针操作T& operator*(){return _pNode-…

【剑指offer】_05 连续子数组最大和

题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢&#…

排序上---(排序概念,常见排序算法,直接插入,希尔排序,直接选择排序,堆排序)

排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&…

排序下---(冒泡排序,快速排序,快速排序优化,快速排序非递归,归并排序,计数排序)

排序上 排序上 交换类排序 基本思想&#xff1a;所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置&#xff0c;交换排序的特点是&#xff1a;将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 冒泡…

哈希的概念及其操作

哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较。顺序查找时间复杂度为O(N)&#xff0c;平衡树中为树的高度&#xff0c;即O( Log2N)&#xff0c;搜索的效率取决…