目录

1.做题目,内存分区

2.malloc/calloc/realloc区别

3.C++申请内存的方式

3.1 new/delete的作用

4.malloc和operator new 和 new的区别

5.定位new

6.内存泄漏问题

6.1 什么是内存泄露? 


1.做题目,内存分区

数据段(静态区):存放全局或者静态变量;

解:

        globalVar是全局变量,在数据段(静态区),选C;

        staticGlobalVar是全局静态变量,在数据段(静态区),选C;

        staticVar是局部静态变量,在数据段(静态区),选C;

        这三个变量的区别是,它们的生命周期是整个程序运行期间;声明的时候globalvar是第一个,staticGlobalVar是第二个,staticVar是第三个;

        globalvar是在所有文件都可见,一旦包含了这个文件,此时包含这个文件的那个文件如果起了同名的变量,就会出现问题;

        staticGlobalVar只会在本文件中可见,其他文件即使包含这个文件,也不会访问到这个文件。

        localvar是局部变量,在栈上,选A;

        num1是一个数组,40个字节,10个元素,在栈上,选A;

        char2是一个数组,5个字节,包含\0,5个元素,存在栈上,选A;

        *char2是数组的第一个元素,数组在栈上,那么首元素也一定在栈上,选A;

        pChar3是一个局部变量,指针,32位cpu就4个字节,在栈上,选A;

        *pChar3保存的是字符串首元素的地址,而字符串是在常量区(代码段),选D

        ptr1是一个局部指针,在栈上,选A;

        *ptr由于是malloc开辟的空间,所以在堆上,选B

2.malloc/calloc/realloc区别

malloc:申请空间;

calloc:申请空间+将每一个空间初始化为0;

realloc:对原来的空间进行扩容;

3.C++申请内存的方式

C++使用操作符new,就能开辟空间,返回这个类型的指针;

销毁函数的时候使用delete操作符进行内存的回收;

使用new还能对空间进行初始化具体如下:

3.1 new/delete的作用

对于基本类型,和c语言的malloc和free没有任何区别,唯一的区别是自定义类型,例如:

当使用new的时候,会调用类的构造函数,默认将a初始化为0;而c语言本质只会申请空间,c++不仅可以申请空间,还能调用构造函数进行初始化

free函数和delete函数同理:

free函数只是释放空间,delete不仅能释放空间,还能调用析构函数

4.malloc和operator new 和 new的区别

malloc只会创建内存;

operator new 创建内存 + 创建失败抛异常; 等同于malloc + 失败抛异常;

new 创建内存 + 创建失败抛异常 + 调用构造函数;等同于 malloc + operator new + 调用构造函数;

注意:这里创建所有的空间都是在堆上进行的,速度比较慢,后面学到内存池,会有另一种方法;

面试题:malloc 和new的区别?

1.new 会调用构造函数,内存创建失败了会抛异常;malloc失败了会返回0;

2.malloc是一个函数;new是一个操作符;

3.malloc用法:参数传入字节数,返回值是void*,new后面跟申请对象的类型,返回值是该类型的指针;

5.定位new

当只想在已有的空间调用构造函数进行初始化,该如何操作?

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class A 
{
private:
	int a;
public:
	A() {};
	A(int val):a(val)
	{}
	~A(){}
};


int main() 
{
	A* pn = new A(10);

	// 下面两步等同于上面一步
	A* p = (A*) operator new(sizeof(A)); // 仅分配内存,不调用构造函数
	new(p)A(10); // 对已经存在的空间调用构造函数初始化

	p->~A();
	operator delete(p);

	return 0;
}

1.首先使用operator new分配空间,此时并没有调用构造函数进行初始化;

2.使用定位new,即 new(已经分配好空间的指针)A(构造形参)

3.此时就完成了new的功能,即分配内存空间并调用构造函数进行初始化;

6.内存泄漏问题

        在java中基本很少存在这个问题,因为存在一个垃圾回收机制。

6.1 什么是内存泄露? 

下面的代码申请了1G字节的空间,但是在使用完毕之后没有释放,此时其他人想要使用这块内存,是无法使用的的,因为已经被占用了,这就叫内存泄露;糙一点说就是,占着茅坑不拉屎;

char* p = new char[1024*1024*1024];

如果长期运行的进程,如果每次执行一个任务会导致内存泄露,最后会导致程序崩溃;

valgrind是可以检测内存泄露的一个小工具,可以了解一下;

如何规避内存泄露呢?一个就是写代码的规范问题,还有一个就是可以使用c++11的智能指针,这在后面的部分会介绍到。

面试题:如何在堆上申请4G的空间

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>

using namespace std;


// 堆上申请4G内存空间?
int main()
{
	size_t n = 4; // 这里不用int的原因是,int会溢出
	try
	{
		void* p = new char[n * 1024 * 1024 * 1024]; // 此时会报错
		cout << "new :" << p << endl;
	}
	catch (exception& e)
	{
		cout << e.what() << endl;
	}
}

由于进程地址空间不够大,所以程序会崩溃;从原来的2^32次方到了2^64次方(40亿个4G),只需要将平台从32位换到64位使进程空间地址变大;

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐