在c ++中可以动态分配的最大内存和编译时间
我在玩耍以了解可以分配多少内存。 最初我认为可以分配的最大内存等于物理内存(RAM)。 我通过运行命令在Ubuntu 12.04上检查了我的RAM,如下所示:
~$ free -b
total used free shared buffers cached
Mem: 3170848768 2526740480 644108288 0 265547776 1360060416
-/+ buffers/cache: 901132288 2269716480
Swap: 2428497920 0 2428497920
如上所示,总物理内存是3Gig(3170848768字节),其中只有644108288字节是空闲的,所以我认为我可以在最大分配内存。 我通过编写下面只有两行的小程序来测试它:
char * p1 = new char[644108290] ;
delete p1;
由于代码完美运行,这意味着它成功分配了内存。 此外,我试图分配内存大于可用的物理空闲内存,但它并没有抛出任何错误。 然后每个问题
malloc可以分配的最大内存
我认为它一定是使用虚拟内存。所以我测试了免费交换内存的代码,它也工作。
char * p1 = new char[2428497920] ;
delete p1;
我试图分配空闲的交换加上可用的RAM字节的内存
char * p1 = new char[3072606208] ;
delete p1;
但是这段代码没有抛出bad_alloc
异常。为什么代码这次没有工作。
现在我在编译时在一个新程序中分配内存,如下所示:
char p[3072606208] ;
char p2[4072606208] ;
char p3[5072606208];
cout<<"Size of array p = " <<sizeof p <<endl;
cout<<"Size of array p2 = " <<sizeof p2<<endl;
cout<<"Size of array p2 = " <<sizeof p3;
输出节目
Size of array p = 3072606208
Size of array p1 = 4072606208
Size of array p2 = 777638912
你能帮我理解这里发生了什么吗? 为什么它允许在编译时分配内存,而不是动态分配内存。 在分配编译时间时, p
和p1
如何分配比swap更多的内存以及可用的RAM内存。 p2
失败的地方。 这是如何工作的。 这是一些未定义的行为或操作系统特定的行为。 谢谢你的帮助。 我使用Ubuntu 12.04和gcc 4.6.3。
内存页面在您使用它们之前并不实际映射到您的程序。 所有的malloc
都会保留一个虚拟地址空间的范围。 在尝试读取或写入物理RAM之前,没有将物理RAM映射到这些虚拟页面。
即使您分配全局或堆栈(“自动”)内存,在您触摸它们之前也没有物理页面的映射。
最后, sizeof()
是在编译时计算的,当编译器不知道OS将在以后做什么时。 所以它只会告诉你对象的预期大小。
如果您尝试在每种情况下将内存memset
为0,您会发现事情会表现得非常不同。 另外,你可能想尝试一下calloc
,它将它的内存归零。
有趣的是......有一件事要注意:当你写作的时候
char p[1000];
您在堆栈上分配(保留)100个字节。
当你写
char* p = malloc(100);
你在堆上分配100个字节。 巨大差距。 现在我不知道为什么堆栈分配正在工作 - 除非编译器将[]中的值作为int读取,并因此分配更小的块。
大多数操作系统都不会分配物理内存,它们会为您提供虚拟地址空间中的页面,这些空间在您使用之前一直未使用(并因此未分配),然后CPU的内存管理器单元将为您提供内存要求。 尝试写入你分配的字节,看看会发生什么。
此外,至少在Windows中,当您分配一块内存时,您只能保留OS可用的最大连续块 - 因为内存被重复分配碎片化,您可以减少malloc的最大侧块。 我不知道Linux是否也有这个问题。
这两个程序之间有很大的区别:
program1.cpp
int main () {
char p1[3072606208];
char p2[4072606208];
char p3[5072606208];
std::cout << "Size of array p1 = " << sizeof(p1) << std::endl;
std::cout << "Size of array p2 = " << sizeof(p2) << std::endl;
std::cout << "Size of array p3 = " << sizeof(p3) << std::endl;
}
program2.cpp:
char p1[3072606208];
char p2[4072606208];
char p3[5072606208];
int main () {
std::cout << "Size of array p1 = " << sizeof(p1) << std::endl;
std::cout << "Size of array p2 = " << sizeof(p2) << std::endl;
std::cout << "Size of array p3 = " << sizeof(p3) << std::endl;
}
第一个分配堆栈上的内存; 由于堆栈溢出,将会出现分段错误。 第二个没有太大的作用。 那个记忆还不完全存在。 它是以数据段的形式未被触及的。 让我们修改第二个程序,以便触及数据:
char p1[3072606208];
char p2[4072606208];
char p3[5072606208];
int main () {
p1[3072606207] = 0;
p2[3072606207] = 0;
p3[3072606207] = 0;
std::cout << "Size of array p1 = " << sizeof(p1) << std::endl;
std::cout << "Size of array p2 = " << sizeof(p2) << std::endl;
std::cout << "Size of array p3 = " << sizeof(p3) << std::endl;
}
这不会为堆或堆栈上的p1
, p2
或p3
分配内存。 该记忆存在于数据段中。 它是应用程序本身的一部分。 这有一个大问题:在我的机器上,这个版本甚至不会链接。
上一篇: Maximum memory that can be allocated dynamically and at compile time in c++
下一篇: If free() knows the length of my array, why can't I ask for it in my own code?