我正在编写一个泄漏内存(主内存)的程序,以测试系统在低系统内存和交换内存时的行为方式。我们使用以下循环定期运行并泄漏内存
main(int argc, char* argv[] )
{
int arg_mem = argv[1];
while(1)
{
u_int_ptr =(unsigned int*) malloc(arg_mem * 1024 * 1024);
if( u_int_ptr == NULL )
printf("\n leakyapp Daemon FAILED due to insufficient available memory....");
sleep( arg_time );
}
}
上面的循环运行一段时间并打印消息“leakyapp Daemon FAILED由于可用内存不足......”。但是当我运行命令“free”时,我可以看到运行该程序对主内存或交换没有影响。
我做错了吗?
答案 0 :(得分:8)
在您实际写入之前,物理内存不会提交给您的分配。
如果你有2.6.23之后的内核版本,请使用带有mmap()
标志的MAP_POPULATE
代替malloc()
:
u_int_ptr = mmap(NULL, arg_mem * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
if (u_int_ptr == MAP_FAILED)
/* ... */
如果您有较旧的内核,则必须触摸分配中的每个页面。
答案 1 :(得分:3)
可能存在某种写时复制优化。我建议实际上在你正在分配的内存中写一些内容。
答案 2 :(得分:1)
正在发生的事情是malloc从堆中请求argmem * 256页(假设页面大小为4 KB)。堆反过来从操作系统请求内存。但是,所有这一切都是在页表中为新分配的内存块创建条目。除了堆跟踪malloc请求所需的物理RAM之外,没有为该进程分配实际的物理RAM。
只要进程尝试通过读取或来访问其中一个页面,就会生成页面错误,因为页面表中的条目实际上是一个悬空指针。然后,操作系统将为该进程分配一个物理页面。只有这样你才能看到可用的物理内存下降。
由于所有新页面都开始完全归零,因此Linux可能会采用“写入时复制”策略来优化页面分配。即,它可能使单个页面完全归零,并且当进程尝试从先前未使用的页面读取时始终分配该页面。只有当进程尝试写入该新页面时,它才会实际从物理RAM分配一个完全新鲜的页面。我不知道Linux是否真的这样做,但如果确实如此,仅仅从新页面读取就不足以增加物理内存的使用。
所以,你最好的策略是分配你的大块RAM,然后以4096字节的间隔写一些东西。
答案 3 :(得分:0)
ulimit -m -v
打印什么?
说明:在任何服务器操作系统上,您可以限制进程可以分配的资源量,以确保单个失控进程无法关闭整个计算机。
答案 4 :(得分:0)
我猜测(基于命令行参数)您使用的是桌面/服务器操作系统,而不是嵌入式系统。
像这样分配内存可能不会消耗太多RAM。您的内存分配可能甚至没有成功 - 在某些操作系统(例如Linux)上,即使您要求的内存超过可用内存,malloc()
也可以返回非NULL。
在不知道您的操作系统是什么以及您正在尝试测试的内容的情况下,很难提出具体的建议,但您可能希望查看比malloc()
更多的低级别内存分配方式,或者控制虚拟内存系统。在Linux上,您可能需要查看mlock()
。
答案 5 :(得分:0)
我认为caf已经解释过了。 Linux通常配置为允许过度使用内存。你分配了大量的内存,但内部却没有发生任何事情,只是记下你处理过的大量内存。在您尝试编写该块之前,内核不会尝试查找可用的虚拟内存来满足读/写访问。这有点像航班预订:航空公司通常超量预订航班,因为总有一部分乘客没有出现。
您可以通过在分配后使用memset()
写入块来强制提交内存。 calloc
也应该有用。