C++ 内存分配失败,即使内存仍然足够
我正在Linux(Ubuntu13.04)上工作,目前我有一个问题:为什么内存分配会失败,即使内存仍然足够 我今天编写了一个简单的测试应用程序,在运行这个测试应用程序时遇到了这个问题。下面是我用来进行测试的代码片段:C++ 内存分配失败,即使内存仍然足够,c++,linux,memory,process,C++,Linux,Memory,Process,我正在Linux(Ubuntu13.04)上工作,目前我有一个问题:为什么内存分配会失败,即使内存仍然足够 我今天编写了一个简单的测试应用程序,在运行这个测试应用程序时遇到了这个问题。下面是我用来进行测试的代码片段: #include <stdio.h> #include <unistd.h> #include <list> #include <vector> #include <string
#include <stdio.h>
#include <unistd.h>
#include <list>
#include <vector>
#include <strings.h>
using namespace std;
unsigned short calcrc(unsigned char *ptr, int count)
{
unsigned short crc;
unsigned char i;
//high cpu-consumption code
//implements CRC algorithm: Cylic
//Redundancy code
}
void* CreateChild(void* param){
vector<unsigned char*> MemoryVector;
pid_t PID = fork();
if (PID == 0){
const int MEMORY_TO_ALLOC = 1024 * 1024;
unsigned char* buffer = NULL;
while(1){
buffer = NULL;
try{
buffer = new unsigned char [MEMORY_TO_ALLOC]();
calcrc(buffer, MEMORY_TO_ALLOC );
MemoryVector.push_back(buffer);
} catch(...){
printf("an exception was thrown!\n");
continue;
} //try ... catch
} //while
} // if pid == 0
return NULL;
}
int main(){
int children = 4;
while(--children >= 0){
CreateChild(NULL);
};
while(1) sleep(3600);
return 0;
}
可能您的地址空间中没有更多1MB顺序内存页。你有自由空间碎片 在我的测试中,当内存大约为220M时,上面的代码开始抛出异常。从现在起,应用程序似乎无法获得更多的内存,因为TOP命令显示的可用内存仍然保持在210M以上。那么为什么会发生这种情况呢
top
的输出每N秒更新一次(已配置),并且不会真正显示当前状态
另一方面,内存分配非常快
发生的情况是,您的程序占用内存,并且在某个点(当顶部显示200 Mb空闲时)它开始失败。您正在x86-32上运行,因此您的进程是32位的。即使使用更多内存+交换,它们也会受到地址空间的限制,请运行:
grep “HIGHMEM” /boot/config-`uname -r`
grep “VMSPLIT” /boot/config-`uname -r`
查看内核是如何配置的
也许您的4个子进程仅限于3G,并且正在使用12G+其他进程~700M来达到您看到的数字
编辑:
因此,内核被配置为给每个用户空间进程3G的地址空间,其中一些地址空间将被程序、库和初始运行时内存占用(由于fork而共享)
因此,您有4个孩子分别使用~3G-~12G+~7800万其他程序。一旦孩子们开始报告错误,这将留下大约220米的空闲空间
您可以运行另一个子进程,也可以使用和64/x86-64版本的Ubuntu重新安装,每个进程将能够分配更多内存。以及一些堆不使用的内存。我同意-可能存在碎片。此外,还不清楚“大约有210M内存”是什么意思。“记忆”在哪里?在系统中?在这个过程中?在swap?@JonWatte中,当系统内存超过210M时,测试应用程序开始抛出异常。我更新了帖子。这不取决于你的系统有多少内存。每个32位进程(我想这是您的情况)都有自己的4GB地址空间。其中几乎有2个进程可以使用(或在某些系统上使用3个)。再也没有了。那么,这个进程到底使用了多少内存?(我不知道如何在linux中检查它)注意,进程本身的可用地址空间实际上可能少于4GB——2GB或3MB是32位进程的典型限制。线程的共享库、可执行文件和堆栈也会占用地址空间。它在使用220M时失败,或者在220M空闲时失败?它是一个32位进程吗?您是否检查了进程是否设置了内存限制(
ulimit
或其他什么?我不知道,我不是linux的家伙)计算机有多少内存和交换空间?@MooingDuck在超过210M可用内存时失败。更新了帖子。第一个是“CONFIG_HIGHMEM64G=y CONFIG_HIGHMEM=y”,第二个是“CONFIG_VMSPLIT_3G=y”@StevePeng,所以答案是您的子进程每个都限于3G。是的,您是对的。如果我在我的应用程序中创建了6个进程,那么在它开始抛出异常之后,其他应用程序会因为内存不足而减慢速度,并且即使使用“free”shell命令也无法启动更多进程。
grep “HIGHMEM” /boot/config-`uname -r`
grep “VMSPLIT” /boot/config-`uname -r`