C++ 为什么此应用程序没有';I don’我不会消耗预期的内存
我编写了一个简单的应用程序来测试内存消耗。在这个测试应用程序中,我创建了四个进程来持续消耗内存,这些进程不会释放内存,除非进程退出 我预计这个测试应用程序将消耗RAM的大部分内存,并导致另一个应用程序减速或崩溃。但结果与预期不一样。代码如下:C++ 为什么此应用程序没有';I don’我不会消耗预期的内存,c++,linux,performance,memory,process,C++,Linux,Performance,Memory,Process,我编写了一个简单的应用程序来测试内存消耗。在这个测试应用程序中,我创建了四个进程来持续消耗内存,这些进程不会释放内存,除非进程退出 我预计这个测试应用程序将消耗RAM的大部分内存,并导致另一个应用程序减速或崩溃。但结果与预期不一样。代码如下: #include <stdio.h> #include <unistd.h> #include <list> #include <vector> using namespace std; uns
#include <stdio.h>
#include <unistd.h>
#include <list>
#include <vector>
using namespace std;
unsigned short calcrc(unsigned char *ptr, int count)
{
unsigned short crc;
unsigned char i;
//high cpu-consumption code
//implements the CRC algorithm
//CRC is Cyclic Redundancy Code
}
void* ForkChild(void* param){
vector<unsigned char*> MemoryVector;
pid_t PID = fork();
if (PID > 0){
const int TEN_MEGA = 10 * 10 * 1024 * 1024;
unsigned char* buffer = NULL;
while(1){
buffer = NULL;
buffer = new unsigned char [TEN_MEGA];
if (buffer){
try{
calcrc(buffer, TEN_MEGA);
MemoryVector.push_back(buffer);
} catch(...){
printf("An error was throwed, but caught by our app!\n");
delete [] buffer;
buffer = NULL;
}
}
else{
printf("no memory to allocate!\n");
try{
if (MemoryVector.size()){
buffer = MemoryVector[0];
calcrc(buffer, TEN_MEGA);
buffer = NULL;
} else {
printf("no memory ever allocated for this Process!\n");
continue;
}
} catch(...){
printf("An error was throwed -- branch 2,"
"but caught by our app!\n");
buffer = NULL;
}
}
} //while(1)
} else if (PID == 0){
} else {
perror("fork error");
}
return NULL;
}
int main(){
int children = 4;
while(--children >= 0){
ForkChild(NULL);
};
while(1) sleep(1);
printf("exiting main process\n");
return 0;
}
虽然CPU很高,但内存百分比仍为0.0。怎么可能呢
free shared buffers cached
Mem: 3083796 0 55996 428296
4G内存中的可用内存超过3G有人知道为什么这个测试应用程序不能按预期工作吗?如果你想占用大量内存:
int mb = 0;
char* buffer;
while (1) {
buffer = malloc(1024*1024);
memset(buffer, 0, 1024*1024);
mb++;
}
在进行一些文件I/O定时测量时,我使用类似这样的方法来确保文件缓冲区缓存为空
正如其他答案已经提到的,您的代码在分配缓冲区后不会写入缓冲区。此处,memset用于写入缓冲区。要将注释转换为答案:
- Linux不会为进程分配内存页,直到它写入内存页(写时复制)
- 此外,您不会在任何地方写入缓冲区,因为
,而无符号字符的默认构造函数
默认初始化所有项new[]
unsigned char
的默认初始化,这是一个无操作:
buffer = new unsigned char [TEN_MEGA];
如果要强制提交,请使用零初始化:
buffer = new unsigned char [TEN_MEGA]();
fork()
在父级中返回PID,在子级中返回0。您编写的ForkChild
将在父级而不是子级中执行所有工作
标准的
new
操作符永远不会返回null;如果分配内存失败,它将抛出(但由于过度分配,它实际上在Linux中也不会这样做)。这意味着您在分配后对缓冲区的测试是没有意义的:它将始终执行第一个分支,或者永远不会到达测试。如果希望返回空值,则需要编写new(std::nothrow).
。包括
,使其工作。但是您的程序实际上正在做您期望它做的事情。正如答案所指出的(@Michael Foukarakis's),未使用的内存不会被分配。在top
程序的输出中,我注意到virt
列上有大量内存用于运行程序的每个进程。后来我在谷歌上搜索了一下,我看到了这是什么:
VIRT--虚拟内存大小(KiB)。任务使用的虚拟内存总量。
包括所有代码、数据和共享库,以及已调出的页面和已映射但未使用的页面。
如您所见,您的程序实际上为自己生成了内存,但它是以页面的形式并存储为虚拟内存。我认为这样做是明智的
这篇文章的一个片段
页、内存页、或虚拟页——一个固定长度的连续虚拟内存块,它是以下各项的最小数据单元:
- 由操作系统为程序执行的内存分配;及
- 在主存储器和任何其他辅助存储器(如硬盘驱动器)之间进行传输
…因此,一个程序可以寻址比计算机中实际存在的内存更多的(虚拟)RAM。虚拟内存是一种让用户产生使用大块连续内存空间(甚至可能比真实内存大)的错觉的方案,而实际上他们的大部分工作都在辅助存储器(磁盘)上。根据需要将作业的固定大小块(页)或可变大小块读入主内存
来源:
除非您对内存页进行写入,否则Linux实际上不会分配内存页。我没有看到你在任何地方向缓冲区写东西@한국매미 new[]
default初始化所有项目。@CoryNelson是的,unsigned char
的默认初始化是否定操作:不涉及写入。@CoryNelson@한국매미 如果你把你的评论作为对这篇文章的回答,我会接受。为什么每次分配一个MB?为什么不直接分配几百MB或GB?当然,再乘以1024。好的,我已经编辑了一点。更好?如果你仍然认为它毫无价值,告诉我,这样我就可以删除它了。@Puppy很久以前,但是你还想看到其他的变化吗?哦,我又困惑了。如果程序实际上保留了内存,为什么我通过运行“无外壳”命令(我的计算机的RAM是4G字节)得到了“免费3083796”?如果你仍然感到困惑,我已经更新了我的答案,加上我在Unix&Linux exchange网站上找到的答案,我想那里的人会更好地向你解释。是的,你是对的,在判断哪个是子进程时,我确实犯了一个错误。此外,你对新运营商的评论也让我受益匪浅。非常感谢您指出这些!非常简短和有用!如果您的评论来得更早,我可能会做出不同的决定:41;-1使用new
??这个问题不是问最佳实践,而是问内存使用情况。答案简明扼要地说明了这一点——引入任何其他东西只会让它变得错综复杂。
buffer = new unsigned char [TEN_MEGA]();