【发布时间】:2023-03-17 09:33:01
【问题描述】:
malloc/calloc 显然使用交换空间来满足超出可用内存的请求。这几乎使系统挂起,因为磁盘使用指示灯一直亮着。发生在我身上之后,我并不确定为什么,我编写了以下 5 行测试程序来检查这确实是系统挂起的原因,
/* --- test how many bytes can be malloc'ed successfully --- */
#include <stdio.h>
#include <stdlib.h>
int main ( int argc, char *argv[] ) {
unsigned int nmalloc = (argc>1? atoi(argv[1]) : 10000000 ),
size = (argc>2? atoi(argv[2]) : (0) );
unsigned char *pmalloc = (size>0? calloc(nmalloc,size):malloc(nmalloc));
fprintf( stdout," %s malloc'ed %d elements of %d bytes each.\n",
(pmalloc==NULL? "UNsuccessfully" : "Successfully"),
nmalloc, (size>0?size:1) );
if ( pmalloc != NULL ) free(pmalloc);
} /* --- end-of-function main() --- */
如果您的两个命令行参数的乘积超过物理内存,那确实会挂起系统。最简单的解决方案是 malloc/calloc 自动失败的某种方式。更难且不可移植的是编写一个 popen() 的 free 命令的小包装器,解析输出,并且只有在可用的“空闲”内存可以满足请求时才调用 malloc/calloc,也许有一点安全因素内置。
有没有更简单、更便携的方法来实现这一点? (显然类似于这个问题can calloc or malloc be used to allocate ONLY physical memory in OSX?,但我希望得到某种“是”的答案。)
= 决定遵循 Tom 的 /proc/meminfo 建议。也就是说,与其 popen()'ing "free",不如直接解析现有且易于解析的 /proc/meminfo 文件。然后,表单的单行宏
#define noswapmalloc(n) ( (n)
完成工作。如下所示的 memfree() 并不像我想要的那样可移植,但如果/当需要时,可以轻松透明地被更好的解决方案替换,而现在不是。
#include <stdio.h>
#include <stdlib.h>
#define _GNU_SOURCE /* for strcasestr() in string.h */
#include <string.h>
char *strcasestr(); /* non-standard extension */
/* ==========================================================================
* Function: memfree ( memtype )
* Purpose: return number of Kbytes of available memory
* (as reported in /proc/meminfo)
* --------------------------------------------------------------------------
* Arguments: memtype (I) (char *) to null-terminated, case-insensitive
* (sub)string matching first field in
* /proc/meminfo (NULL uses MemFree)
* --------------------------------------------------------------------------
* Returns: ( int ) #Kbytes of memory, or -1 for any error
* --------------------------------------------------------------------------
* Notes: o
* ======================================================================= */
/* --- entry point --- */
int memfree ( char *memtype ) {
/* ---
* allocations and declarations
* ------------------------------- */
static char memfile[99] = "/proc/meminfo"; /* linux standard */
static char deftype[99] = "MemFree"; /* default if caller passes null */
FILE *fp = fopen(memfile,"r"); /* open memfile for read */
char memline[999]; /* read memfile line-by-line */
int nkbytes = (-1); /* #Kbytes, init for error */
/* ---
* read memfile until line with desired memtype found
* ----------------------------------------------------- */
if ( memtype == NULL ) memtype = deftype; /* caller wants default */
if ( fp == NULL ) goto end_of_job; /* but we can't get it */
while ( fgets(memline,512,fp) /* read next line */
!= NULL ) { /* quit at eof (or error) */
if ( strcasestr(memline,memtype) /* look for memtype in line */
!= NULL ) { /* found line with memtype */
char *delim = strchr(memline,':'); /* colon following MemType */
if ( delim != NULL ) /* NULL if file format error? */
nkbytes = atoi(delim+1); /* num after colon is #Kbytes */
break; } /* no need to read further */
} /* --- end-of-while(fgets()!=NULL) --- */
end_of_job: /* back to caller with nkbytes */
if ( fp != NULL ) fclose(fp); /* close /proc/meminfo file */
return ( nkbytes ); /* and return nkbytes to caller */
} /* --- end-of-function memfree() --- */
#if defined(MEMFREETEST)
int main ( int argc, char *argv[] ) {
char *memtype = ( argc>1? argv[1] : NULL );
int memfree();
printf ( " memfree(\"%s\") = %d Kbytes\n Have a nice day.\n",
(memtype==NULL?" ":memtype), memfree(memtype) );
} /* --- end-of-function main() --- */
#endif
【问题讨论】:
-
你可以对你的进程允许使用的内存量设置一个进程限制。
-
ulimit可从 shell 获得,但它只调用getrlimit和setrlimit,您可以从 C 程序中调用它们。getrlimit应该让您看到有效的限制。您还可以查看/proc/meminfo,了解有关您的处理器物理内存的信息。 -
看看
swapoff命令。 -
@rici 谢谢,rici。我也没有意识到这一点。它确实有效! -- 我刚试了一下,swapoff -a 后,如果请求超过可用物理内存,测试程序立即失败。 (get/setrlimit 似乎是最便携的,并且可以在程序中透明地实现,不会影响系统的其余部分。)