【内存分布管理】new与malloc以及delede与delete[]的区别

简介: 【内存分布管理】new与malloc以及delede与delete[]的区别

1.内存分布示意图(重要)

其中数据共享区也叫内存映射段,是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信

2.判断以下程序中的变量在什么区域

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
 static int staticVar = 1;
 int localVar = 1;
 int num1[10] = { 1, 2, 3, 4 };
 char char2[] = "abcd";
 const char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof(int) * 4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
 free(ptr1);
 free(ptr3);
}
  1. 选择题: 选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区) globalVar在哪里?C staticGlobalVa在哪里?C staticVar在哪里?_C localVar在哪里?A

     num1 在哪里?A

     char2在哪里?A *char2在哪里?A pChar3在哪里?A *pChar3在哪里?D ptr1在哪里?A *ptr1在 哪里?B

  1. 填空题: sizeof(num1) = 40; (sizezof 数组名等于整个数组的大小) sizeof(char2) = 5__; strlen(char2) = 4; sizeof(pChar3) =

     4; strlen(pChar3) = 4; sizeof(ptr1) = 4;

  1. sizeof 和 strlen 区别? 答:sizeof 计算的是字节的大小,sizezof 数组名等于整个数组的大小,strlen计算字符串的长度,遇到‘\0’为止

3.new和delete

new和delete是C++动态开辟与释放内存互相匹配的的两个操作符,因此不需要头文件。C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

本质上,new的底层也是通过malloc来实现的

new与delete的使用示例

void Test()
{
  // 动态申请一个int类型的空间
  int* ptr4 = new int;
  
  // 动态申请一个int类型的空间并初始化为10
  int* ptr5 = new int(10);
  
  // 动态申请10个int类型的空间
  int* ptr6 = new int[3];
 
  delete ptr4;
  delete ptr5;
  delete[] ptr6;
}

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[]使用的时候要互相匹配

4.malloc和new的区别

1.属性:new是关键字,而malloc是函数。

2.参数:new操作符会无需指定内存块的大小,编译器会自己根据类型算,而malloc需要显式的指定。

3.返回值类型:newc操作符申请成功时返回该对象类型的指针,无需强制转换,申请失败的时候会报异常。而malloc函数申请成功返回的时void*类型的指针,大多需要强制类型转换,申请失败会返回一个NULL.

4.new可以调用malloc来实现,但是malloc不可以。

5.对于自定义类型开辟空间

对于内置类型,new与malloc几乎没有什么区别,但是对于自定义类型,也就是class,new和delete会调用构造函数和析构函数.

5.delete和delete[]的区别

delete 释放new分配的单个对象指针指向的内存;
delete[] 释放new分配的对象数组指针指向的内存。

对于内置类型

delete和delete[]的效果是一样的

void test2() {
  int* a = new int[4];
  int* b = new int;
  delete[] a;
  delete b;
}

因为对于内置类型,在new分配内存的时候就已经确定了内存的大小,并且记录了下来, 系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数

对于自定义类型:

void test3() {
  A* p1 = new A[5];
  //delete p1;错误
  delete[] p1;
}

delete与delete[]的效果是不一样的,delete只会调用一次析构函数,而delete[]会调用多次。那么delete[]是如何知道需要调用多少次析构函数呢?也就是如何知道对象数组的元素个数呢?如果我们开辟了用new []开辟了对象数组,编译器会在数组的前面再开辟一块空间用来存放元素个数。

此时如果用delete[]释放空间,它会先从上一块区域(32位系统是4字节,64位是8个字节)读取元素个数并释放

这也是为什么用delete 释放对象数组会报错误,因为deletet是从指针p1指向的位置开始,但是实际上p1上一面的内存块也要释放。动态内存不能只释放一部分

5.内存泄漏

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

内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

内存泄漏的分类:

堆内存泄漏(heap leak):

堆内存泄漏是指程序中通过new/malloc等申请到的堆空间没有及时用delete/free释放掉,导致这片空间无法再被申请。

系统内存泄漏

指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。

_CrtDumpMemoryLeaks() 函数

crtdbg模块的c++_CrtDumpMemoryLeaks函数可以检测C、C++代码中的内存泄漏错误。在需要检测的代码前后分别调用_CrtDumpMemoryLeaks函数,就可以看到该代码片段是否发送内存泄漏,以及泄露的空间大小,但是不能提供泄漏的具体地址。注意,要在进入调试窗口才能看到该信息。

如何避免内存泄漏

  1. 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。
  2. 采用RAII思想或者智能指针来管理资源。
  3. 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。
  4. 使用内存泄漏工具检测。
    总结:

1、事前预防型。如智能指针等。2、事后查错型。如泄漏检测工具。

相关文章
|
2月前
|
C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(二)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
2月前
|
编译器 C++ 开发者
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
1天前
|
存储 缓存 资源调度
阿里云服务器经济型、通用算力型、计算型、通用型、内存型实例区别与选择指南
在我们通过阿里云的活动选购云服务器的时候会发现,相同配置的云服务器往往有多个不同的实例可选,而且价格差别也比较大,这会是因为不同实例规格的由于采用的处理器不同,底层架构也有所不同(例如X86 计算架构与Arm 计算架构),因此不同实例的云服务器其性能与适用场景是有所不同。本文将详细解析阿里云的经济型、通用算力型、计算型、通用型和内存型实例的性能特点及适用场景,帮助用户根据自己的业务需求做出明智的选择。
|
1月前
|
存储 缓存 安全
阿里云服务器内存型r7、r8a、r8y、r8i实例区别及选择参考
随着阿里云2024年金秋云创季的开始,目前在阿里云的活动中,属于内存型实例规格的云服务器有内存型r7、内存型r8a、内存型r8y和内存型r8i这几个实例规格,相比于活动内的经济型e和通用算力型u1等实例规格来说,这些实例规格等性能更强,虽然这几个实例规格的云服务器通常处理器与内存的配比为都是1:8,但是他们在处理器、存储、网络、安全等方面等性能并不是一样的,所以他们的适用场景也有着不同。本文为大家介绍内存型r7、r8a、r8y、r8i实例的性能、适用场景的区别以及选择参考。
|
2月前
|
程序员 C语言 C++
C++入门5——C/C++动态内存管理(new与delete)
C++入门5——C/C++动态内存管理(new与delete)
92 1
|
2月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
398 1
|
2月前
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
85 0
|
1月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
291 1
|
22天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
1月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80

热门文章

最新文章