如果请求超过可用物理内存(即不使用交换),如何使malloc/calloc失败
malloc/calloc显然使用交换空间来满足超出可用内存的请求。由于磁盘使用指示灯一直亮着,这几乎使系统挂起。在这件事发生在我身上之后,我不知道为什么,我写了下面的5行测试程序来检查这确实是系统挂起的原因如果请求超过可用物理内存(即不使用交换),如何使malloc/calloc失败,c,linux,malloc,C,Linux,Malloc,malloc/calloc显然使用交换空间来满足超出可用内存的请求。由于磁盘使用指示灯一直亮着,这几乎使系统挂起。在这件事发生在我身上之后,我不知道为什么,我写了下面的5行测试程序来检查这确实是系统挂起的原因 /* --- test how many bytes can be malloc'ed successfully --- */ #include <stdio.h> #include <stdlib.h> int main ( int argc, char *arg
/* --- 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() --- */
/*--测试可以成功删除多少字节--*/
#包括
#包括
int main(int argc,char*argv[]){
unsigned int nmalloc=(argc>1?atoi(argv[1]):10000000),
大小=(argc>2?原子(argv[2]):(0));
无符号字符*pmalloc=(大小>0?calloc(nmalloc,大小):malloc(nmalloc));
fprintf(标准输出,“%s malloc'ed%d个元素,每个元素有%d个字节。\n”,
(pmalloc==NULL?“未成功”:“成功”),
nmalloc(尺寸>0?尺寸:1));
如果(pmalloc!=NULL)自由(pmalloc);
}/*--函数main()结束--*/
如果两个命令行参数的乘积超过物理内存,那么这确实会挂起系统。最简单的解决方案是malloc/calloc自动失败。更难且不可移植的是编写一个小包装器,使popen()是一个空闲命令,解析输出,并且只有在可用的“空闲”内存可以满足请求的情况下才调用malloc/calloc,可能内置了一点安全系数
有没有更简单、更便携的方法来实现这一点?(显然与这个问题类似,但我希望得到某种“是”的答案。)
E-d-i-t------------
决定遵循Tom的/proc/meminfo建议。也就是说,与popen()的“free”不同,只需直接解析现有且易于解析的/proc/meminfo文件。然后是表单的单行宏 #定义noswapmalloc(n)((n)<1000l*memfree(NULL)/2?malloc(n):NULL) 完成工作。如下所示,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
#包括
#包括
#为string.h中的strcasestr()定义_GNU_SOURCE/**/
#包括
char*strcasestr();/*非标准扩展*/
/* ==========================================================================
*功能:memfree(memtype)
*用途:返回可用内存的KB数
*(如/proc/meminfo中所述)
* --------------------------------------------------------------------------
*参数:memtype(I)(char*)以null结尾,不区分大小写
*(子)字符串匹配中的第一个字段
*/proc/meminfo(NULL使用MemFree)
* --------------------------------------------------------------------------
*返回:(int)#Kbytes内存,或任何错误返回-1
* --------------------------------------------------------------------------
*注:o
* ======================================================================= */
/*---入口点--*/
int memfree(char*memtype){
/* ---
*分配和申报
* ------------------------------- */
静态char memfile[99]=“/proc/meminfo”;/*linux标准*/
静态char deftype[99]=“MemFree”/*如果调用方传递null,则为默认值*/
FILE*fp=fopen(memfile,“r”);/*打开memfile进行读取*/
char memline[999];/*逐行读取memfile*/
int-nkbytes=(-1);/*#Kbytes,init表示错误*/
/* ---
*读取memfile,直到找到具有所需memtype的行
* ----------------------------------------------------- */
如果(memtype==NULL)memtype=deftype;/*调用者想要默认值*/
如果(fp==NULL)转到\u作业的\u;/*的\u,但我们无法获取它*/
而(fgets(memline,512,fp)/*读取下一行*/
!=NULL){/*在eof时退出(或错误)*/
if(strcasestr(memline,memtype)/*在行中查找memtype*/
!=NULL){/*找到了memtype为的行*/
char*delim=strchr(memline,:');/*MemType后面的冒号*/
如果(delim!=NULL)/*NULL文件格式错误*/
冒号后的nkbytes=atoi(delim+1);/*num为#Kbytes*/
break;}/*无需进一步阅读*/
}/*---时间结束(fgets()!=NULL)--*/
结束\u作业:/*返回到具有NK字节的调用者*/
如果(fp!=NULL)fclose(fp);/*关闭/proc/meminfo文件*/
返回(nkbytes);/*并将nkbytes返回给调用者*/
}/*--函数memfree()的结尾--*/
#如果已定义(MEMFREETEST)
int main(int argc,char*argv[]){
char*memtype=(argc>1?argv[1]:NULL);
int memfree();
printf(“memfree(\%s\”)=%d千字节\n祝您今天愉快。\n“,
(memtype==NULL?“:memtype),memfree(memtype));
}/*--函数main()结束--*/
#恩迪夫
malloc/calloc显然使用交换空间来满足超出可用内存的请求
嗯,没有
Malloc/calloc使用虚拟内存。“虚拟”意味着它不是真实的——它是一种由谎言和谎言构成的人为的幻觉。你的整个过程都是建立在这些人为构造的幻觉之上的——线程是一个虚拟CPU,套接字是一个虚拟网络连接,C语言实际上是一个“C抽象机”的规范,进程是一个虚拟计算机(实现了这些语言的抽象机)
你不应该看魔法幕后面。你不应该知道物理内存的存在。系统没有挂起-只是错觉比较慢,但这很好,因为C抽象机没有说明任何东西需要多长时间,也没有提供任何性能保证
更重要的是,;
#include <stdio.h>
#include <stdlib.h>
int main ( int argc, char *argv[] ) {
/* These three lines were added */
void* tmp = calloc(1000, 1); /* force initialization */
printf("Allocated 1000 bytes at %p\n", tmp);
free(tmp);
/* The rest is unchanged */
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);
}
$ gcc -Og -ggdb -Wall -o mall mall.c
$ # A simple malloc completes instantly without page faults
$ /usr/bin/time ./mall 4000000000
Allocated 1000 bytes at 0x55b94ff56260
Successfully malloc'ed -294967296 elements of 1 bytes each.
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1600maxresident)k
0inputs+0outputs (0major+61minor)pagefaults 0swaps
$ # Unless we tell malloc to initialise memory
$ MALLOC_PERTURB_=35 /usr/bin/time ./mall 4000000000
Allocated 1000 bytes at 0x5648c2436260
Successfully malloc'ed -294967296 elements of 1 bytes each.
0.19user 1.23system 0:01.43elapsed 99%CPU (0avgtext+0avgdata 3907584maxresident)k
0inputs+0outputs (0major+976623minor)pagefaults 0swaps
# Same, with calloc. No page faults, instant completion.
$ /usr/bin/time ./mall 1000000000 4
Allocated 1000 bytes at 0x55e8257bb260
Successfully malloc'ed 1000000000 elements of 4 bytes each.
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1656maxresident)k
0inputs+0outputs (0major+62minor)pagefaults 0swaps
$ # Again, setting the magic malloc config variable changes everything
$ MALLOC_PERMUTE_=35 /usr/bin/time ./mall 1000000000 4
Allocated 1000 bytes at 0x5646f391e260
Successfully malloc'ed 1000000000 elements of 4 bytes each.
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1656maxresident)k
0inputs+0outputs (0major+62minor)pagefaults 0swaps