赞
踩
栈、(内存映射段)自由存储段、堆、(数据段)全局/静态存储区、(代码段)常量存储区
由程序员分配和释放,若不释放,程序结束时由会由OS回收
堆仅存在动态分配,没有静态分配的堆,所以在申请空间之后,在使用完后最好甚至必须手动对其进行释放,以避免内存泄漏
基本的malloc/realloc/free 函数维护了一套内部的堆数据结构。当程序使用这些函数去获得新的内存空间时,这套函数首先试图从内部存储空间中寻找可用的内存空间,如果没有可以使用的内存空间,则试图利用系统调用来动态增加程序数据段的内存大小,新分配得到的空间首先被组织进内部堆中去,然后再以适当的形式返回给调用者。当程序释放分配的内存空间时,这片内存空间被返回内部堆结构中,可能会被适当的处理(比如和其他空闲空间合并成更大的空闲空间),以更适合下一次内存分配申请。
该概念由C++引入,除去该区域即C中的内存分区
“Note that while the default global new and delete might be implemented in terms of malloc and free by a particular compiler, the heap is not the same as free store and memory allocated in one area cannot be safely deallocated in the other.” --Herb Sutter《exceptional C++》
由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
char* f()
{
//s数组存放于栈上
char s[4] = {'1','2','3','0'};
return s; //返回s数组的地址,但程序运行完s数组就被释放了
}
int main()
{
char *s;
s = f();
printf ("%s", s); //打印出来乱码。因为s所指向地址已经没有数据
}
但值得一提的是,指针和数组在指向字符串时,还存在较大的区别,关于C/C++中数组与指针指向字符串的特性不同处的分析具体可以看看这篇博客http://t.csdn.cn/pTOPZ
由此我们不难理解,对于返回值为指针类型的函数,除非其指针的地址指向静态区或常量区或堆区,否则都会其打印值都会是随机值
注意:不是要求指针存储在静态区/常量区/堆区,局部指针变量除static修饰,其余指针都存储在栈上,必须的是指针指向内容存在静态区/常量区/堆区,其指向内容不会自动销毁,外部通过同一地址仍能调用
PS:对于 char* arr = “hello world”; //字符常量 该行代码c++中无法直接赋值,因为const char*->char*权限放大;但c中允许如此赋值
//指针指向内容存在常量区/静态区 char* test() { char* arr = "hello world"; //字符常量 c++中无法直接赋值,因为const char*->char*权限放大;但c中允许如此赋值 //static char arr[] = "hello world!"; return arr; } void test_() { char* s = test(); printf("s = %s\n", s); } int main() { test_(); return 0; } —————————————————————————————————————————————————————————————————————————————————————————————— //指针指向对象存在堆区 char *getstring() { char *p; p = (char*)malloc(100); strcpy(p, "hello"); return p; } void test() { char *ret = getstring(); printf("%s\n", ret); free(ret); ret = NULL; } int main() { test(); return 0; }
存储全局变量、静态变量,全局区的数据在程序结束后由OS释放
没什么疑惑点的点,存储全局变量、static修饰的所有变量、const修饰的全局变量;
在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
其中BSS存储未初始化变量,DATA存储已初始化变量
用以存储可执行代码的二进制代码与只读常量,在程序结束后由OS释放
表面上似乎明显的区别在于:malloc在堆上分配的内存块,使用free释放内存,而new所申请的内存则是在自由存储区上,使用delete来释放。
但再进一步思考,大部分编译器new与delete的底层默认实现方式还是malloc和free,由此看来似乎堆和自由存储区又没有区别了,或者说自由存储区是基于堆实现的?
但是C++还存在operator重载的语法,基于此,程序员可以通过operator new/delete用自己希望的方式来实现,改用其他内存来实现自由存储,例如全局变量做的对象池,这时自由存储区就区别于堆了。
实际上在C++标准草案中关于这两种区域是否有联系的问题一直很谨慎地没有给予详细说明,而且特定情况下new和delete是按照malloc和free来实现,但这两种内存区域的访问与运作方式不完全同,所以也不应该被完全当成一样的东西来使用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。