通过下面程序在Linux环境下验证C语言的内存分区
#include
#include
int g_val1 = 1;
int g_val2 ;
int main()
{
printf("code_addr:%p\n", main);
const char* str = "hello world";
printf("read_only:%p\n", str);
printf("i n i t :%p\n", &g_val1);
printf("un _ init:%p\n", &g_val2);
char* p1 = (char*)malloc(10 * sizeof(char));
char* p2 = (char*)malloc(10 * sizeof(char));
char* p3 = (char*)malloc(10 * sizeof(char));
printf(" h e a p :%p\n", p1);
printf(" h e a p :%p\n", p2);
printf(" h e a p :%p\n", p3);
printf("s t a c k:%p\n", &str);
printf("s t a c k:%p\n", &p1);
printf("s t a c k:%p\n", &p2);
printf("s t a c k:%p\n", &p3);
return 0;
}
C语言动态内存管理:malloc/calloc/realloc
Windows中提供的内存泄漏检测函数:_CrtDump_MemoryLeaks()
C++中兼容C语言的动态内存管理方式,同时也提出了新的内存管理方式:通过new和delete操作符进行动态内存管理
1.申请单个int类型空间
int* pt = new int;
delete pt;
2.申请连续空间
int* pa = new int[5];
delete[] pa;
3.申请连续空间并赋值
int* pa2 = new int[5]{ 1,2,3,4,5 };
delete[] pa2;
申请自定义类类型的空间时,new会调用构造函数,delete会调用析构函数,malloc和free不会
new和delet函数是用户进行动态内存申请和释放的操作符,operate new和operate delete是系统提供的全局函数,new是在底层调用operate new全局函数来实现的,delete在底层通过调用operate delete全局函数来释放空间。
Date* p1 = new Date;
可以看到new操作符申请类类型空间时,会先调用该类的构造函数,然后调用operate new函数。而operate new函数在底层调用malloc函数,如图:
对于operate new函数,在while循环中,通过malloc循环从堆上申请空间,如果申请成功,则返回空间的首地址,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛出异常。所以operate new一旦返回了,在程序中拿到的肯定是有效堆空间.
delete p1;
delete在删除类类型对象申请的空间时,会先调用析构函数清理资源,再调用operate delete函数。operate delete函数在底层会调用free函数释放空间,如图:
对于内置类型,malloc和new,delete和free基本相似,不同的地方是:new[]和delete[]申请释放的是连续空间,new在申请失败时会抛出异常,malloc会返回NULL
new的原理
delete的原理
new T[N]的原理
delete[]的原理
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用格式:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化
void Test()
{
Date* pt = (Date*)malloc(sizeof(Date));
new(pt) Date;
}
调用malloc函数申请内存后,pt指向了一段和Test对象相同大小的空间,此时没有调用构造函数,所以并没有创建对象,使用定位new表达式会调用构造函数,创建对象。
malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:
如何避免内存泄漏:事前预防,如使用智能指针,事后查错型,使用内存泄漏检测工具。
int main()
{
void* p = new char[0xfffffffful];
cout << "new:" << p << endl;
system("pause");
return 0;
}
ul:unsigned long的简写,表示无符号长整型