目录
2. C语言中动态内存管理方式:malloc/calloc/realloc/free
4. operator new与operator delete函数(重要点进行讲解)
4.1 operator new与operator delete函数(重点)
6. 定位new表达式(placement-new) (了解)
1. C/C++内存分布
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int globalvar = 1;
static int staticGlobalVar = 1;
void test01()
{
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);
}
int main()
{
test01();
system("pause");
return 0;
}
1. 选择题:选项 : A . 栈 B . 堆 C . 数据段 ( 静态区 ) D . 代码段 ( 常量区 )globalVar 哪里? _C___ staticGlobalVar 在哪里? __C__staticVar 在哪里? __C localVar 在哪里?A ___num1 在哪里? _A___char2 在哪里? _B___ * char1 在哪里?B _pChar3 在哪里? _A__ * pChar3 在哪里? __C__ptr1 在哪里? __A__ * ptr1 在哪里? __B__ptr2 在哪里?A *ptr2在哪里 Bptr3 在哪里 A *ptr3 在哪里 B2. 填空题:sizeof ( num1 ) = ____ ;sizeof ( char2 ) = ____ ; strlen ( char2 ) = ____ ;sizeof ( pChar3 ) = ____ ; strlen ( pChar3 ) = ____ ;sizeof ( ptr1 ) = ____ ;3. sizeof 和 strlen 区别?
解析:globalVar是一个全局变量,它存储在数据段(静态区)中。
staticGlobalVar是一个静态全局变量,它也存储在数据段(静态区)中
staticVar是一个静态局部变量,它数据段(静态区)中localVar是一个局部变量,它存储在栈上。
num1是一个整型数组,它存储在栈上。
char2是一个字符数组,它存储在栈上。
char2表示char2数组的第一个元素,即数组的首地址。由于char2数组存储在栈上,所以char2也存储在栈上pchr3 本身在栈区,解引用出来的是在常量区 。*char 解出来是在堆区pChar3是一个指向常量字符的指针,它存储在栈上。它指向一个字符串常量,即字符组"abcd"。由于字符串常量存储在数据段(静态区)中,所以*pChar3也存储在数据段(静态区)中ptr1是一个指向整型的指针,它存储在栈上。它通过malloc函数动态分配了一块内存空间,用于存储整型数据。由于动态分配的内存空间存储在堆上,所以*ptr1也存储在堆上.sizeof和strlen是C语言中的两个不同的函数,它们的作用和用法也不同。
sizeof:
- sizeof是一个运算符,用于计算数据类型或变量所占用的字节数。
- 它可以用于任何数据类型,包括基本数据类型(如int、float等)和自定义数据类型(如结构体、数组等)。
- sizeof的结果是一个无符号整数,表示数据类型或变量所占用的字节数。
- 例如,sizeof(int)返回4,表示int类型占用4个字节。
strlen:
- strlen是一个函数,用于计算字符串的长度,即字符串中字符的个数(不包括字符串结束符'\0')。
- 它只能用于字符串,即以'\0'结尾的字符数组。
- strlen的结果是一个整数,表示字符串的长度。
- 例如,strlen("hello")返回5,表示字符串"hello"有5个字符。
总结: sizeof用于计算数据类型或变量所占用的字节数,而strlen用于计算字符串的长度。它们的作用和用法不同,适用于不同的场景。
2. C语言中动态内存管理方式:malloc/calloc/realloc/free
关于malloc、calloc和realloc的区别,它们都是在C语言中用来动态分配内存的函数。具体来说:
malloc函数用于分配指定大小的内存块,并返回一个指向该内存块的指针。它只分配内存,并不对其进行初始化。所以在使用malloc分配的内存之前,需要手动初始化。
calloc函数也用于分配内存,但它会在分配内存的同时将其初始化为0。它接受两个参数,第一个参数是要分配的元素个数,第二个参数是每个元素的大小。它会返回一个指向分配内存的指针。
realloc函数用于重新分配已经分配的内存块的大小。它接受两个参数,第一个参数是指向已分配内存的指针,第二个参数是要重新分配的大小。如果新的大小大于原来的大小,那么realloc会分配更大的内存块,并将原来的数据复制到新的内存块中。如果新的大小小于原来的大小,那么realloc会将多余的部分释放掉。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int globalvar = 1;
static int staticGlobalVar = 1;
void test01()
{
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);
cout<<endl;
free(ptr1);
free(ptr3);
}
void test02(){
int *p1=(int *)malloc(sizeof(int));
free(p1);
int *p2=(int *)calloc(4,sizeof(int));
int *p3=(int *)realloc(p2,sizeof(int));
free(p3);
}
int main()
{
// test01();
test02();
system("pause");
return 0;
}
3. C++内存管理方式
3.1 new/delete操作内置类型
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int globalvar = 1;
static int staticGlobalVar = 1;
void test01()
{
static int staticvar = 1;
int localvar = 1;
int num1[10] = {1, 2, 3, 4};
char char2[] = "abcd";
const char *pChar3 = "abcd";
cout<<*pChar3<<endl;
int *ptr1 = (int *)malloc(sizeof(int) * 4);
int *ptr2 = (int *)calloc(4, sizeof(int));
int *ptr3 = (int *)realloc(ptr2, sizeof(int) * 4);
cout<<endl;
free(ptr1);
free(ptr3);
}
void test02(){
int *p1=(int *)malloc(sizeof(int));
free(p1);
int *p2=(int *)calloc(4,sizeof(int));
int *p3=(int *)realloc(p2,sizeof(int));
// *p2 为什么不用free 进行删除。
free(p3);
}
void test03(){
int *ptr4=new int;
int *ptr5=new int(4);
int *ptr6=new int [10];
delete ptr4;
delete ptr4;
delete [] ptr6;
}
int main()
{
test01();
// test02();
system("pause");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/4e1b99a1374fd0b2ab24e7db6a27cb2b.png)
3.2 new和delete操作自定义类型
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class A
{
public:
A(int a = 0) : _a(a)
{
cout << "A()" << this << endl;
}
~A()
{
cout << "~A()" << this << endl;
}
private:
int _a;
};
void test01()
{
//(A*a )这里是做了一个强制类型转换的,因为malloc () 生成的是一个void*() 一个所用通用的类型的指针
A *a = (A *) malloc(sizeof(A));
A *a2 = new A(1);
// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间
// 还会调用构造函数和析构函数
free(a);
delete (a2);
// 内置类型是几乎是一样的
int *p3 = (int *)malloc(sizeof(int)); // C
int *p4 = new int;
free(p3);
delete p4;
//构建数组的方式。
A* a5=(A*)malloc(sizeof(A)*5);
A* a6=new A[5];
free(a5);
delete []a6;
}
int main()
{
test01();
system("pause");
return 0;
}
4. operator new与operator delete函数(重要点进行讲解)
4.1 operator new与operator delete函数(重点)
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间
失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否
则抛异常。
*/
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{
// report no memory
// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
/*
operator delete: 该函数最终是通过free来释放空间的
*/
void operator delete(void *pUserData)
{
_CrtMemBlockHeader *pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK);
/* block other threads */
__TRY
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg(pUserData, pHead->nBlockUse);
__FINALLY
_munlock(_HEAP_LOCK);
/* release other threads */
__END_TRY_FINALLY
return;
}
/*
free的实现
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK
5. new和delete的实现原理
5.1 内置类型
5.2 自定义类型
6. 定位new表达式(placement-new) (了解)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class A
{
public:
A(int a = 0) : _a(a)
{
cout << "A()" << this << endl;
}
~A()
{
cout << "~A()" << this << endl;
}
private:
int _a;
};
void test01()
{
//(A*a )这里是做了一个强制类型转换的,因为malloc () 生成的是一个void*() 一个所用通用的类型的指针
A *a = (A *)malloc(sizeof(A));
A *a2 = new A(1);
// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间
// 还会调用构造函数和析构函数
free(a);
delete (a2);
// 内置类型是几乎是一样的
int *p3 = (int *)malloc(sizeof(int)); // C
int *p4 = new int;
free(p3);
delete p4;
//构建数组的方式。
A *a5 = (A *)malloc(sizeof(A) * 5);
A *a6 = new A[5];
free(a5);
delete[] a6;
}
void test02()
{
// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没
// 有执行
A *p1 = (A *)malloc(sizeof(A));
new (p1) A; // 注意:如果A类的构造函数有参数时,此处需要传参
p1->~A();
free(p1);
A *p2 = (A *)operator new(sizeof(A));
new (p2) A(10);
p2->~A();
operator delete(p2);
}
int main()
{
// test01();
test02();
system("pause");
return 0;
}
7. 常见面试题
7.1 malloc/free和new/delete的区别
7.2 内存泄漏
7.2.1 什么是内存泄漏,内存泄漏的危害
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class A
{
public:
A(int a = 0) : _a(a)
{
cout << "A()" << this << endl;
}
~A()
{
cout << "~A()" << this << endl;
}
private:
int _a;
};
void test01()
{
//(A*a )这里是做了一个强制类型转换的,因为malloc () 生成的是一个void*() 一个所用通用的类型的指针
A *a = (A *)malloc(sizeof(A));
A *a2 = new A(1);
// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间
// 还会调用构造函数和析构函数
free(a);
delete (a2);
// 内置类型是几乎是一样的
int *p3 = (int *)malloc(sizeof(int)); // C
int *p4 = new int;
free(p3);
delete p4;
//构建数组的方式。
A *a5 = (A *)malloc(sizeof(A) * 5);
A *a6 = new A[5];
free(a5);
delete[] a6;
}
void test02()
{
// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没
// 有执行
A *p1 = (A *)malloc(sizeof(A));
new (p1) A; // 注意:如果A类的构造函数有参数时,此处需要传参
p1->~A();
free(p1);
A *p2 = (A *)operator new(sizeof(A));
new (p2) A(10);
p2->~A();
operator delete(p2);
}
void Func(){
int a,b;
cin>>a>>b;
if(b==0){
throw invalid_argument("b is zero");
}
}
void MemoryLeaks(){
int *p1=(int *)malloc(sizeof(int));
int *p2=new int;
int *p3=new int[10];
try
{
Func();//Func() 是一个抛异常的函数,导致p3 没有执行。
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
delete[] p3;
}
int main()
{
// test01();
// test02();
MemoryLeaks();
system("pause");
return 0;
}
运行结果
![](https://i-blog.csdnimg.cn/blog_migrate/f84472103f80441081194c2e21520938.png)