关注此SO question和 this answer特别是,似乎在 printf 之后调用 setrlimit 使其无法正常工作。
示例代码如下:
#include <stdio.h>
#include <sys/resource.h>
int main()
{
struct rlimit rlp;
FILE *fp[10000];
int i;
printf("Hello\n");
rlp.rlim_cur = 10000;
rlp.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_NOFILE, &rlp);
getrlimit(RLIMIT_NOFILE, &rlp);
printf("limit %lld %lld\n", rlp.rlim_cur, rlp.rlim_max);
for(i=0;i<10000;i++) {
fp[i] = fopen("a.out", "r");
if(fp[i]==0) { printf("failed after %d\n", i); break; }
}
}
这是控制台输出:
Hello
limit 10000 9223372036854775807
failed after 4861
如果我注释第一个 printf
,控制台输出如下:
limit 10000 9223372036854775807
failed after 9967
有什么理由吗?
[编辑] 我正在运行带有 Xcode 4.6.2 的 MAc OS X 10.7.5。
最佳答案
这是一个更好的程序版本,它展示了问题的更多方面。
#include <stdio.h>
#include <sys/resource.h>
#include <err.h>
#include <fcntl.h>
int
main(int argc, char **argv)
{
struct rlimit rl;
int i;
rl.rlim_cur = 10;
rl.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_NOFILE, &rl))
err(1, "setrlimit");
printf("Hello\n");
rl.rlim_cur = 100;
rl.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_NOFILE, &rl))
err(1, "setrlimit");
if (getrlimit(RLIMIT_NOFILE, &rl))
err(1, "getrlimit");
printf("limit %lld\n", rl.rlim_cur);
for(i = 0; i < 10000; i++) {
FILE *fp;
#if 1
if ((fp = fopen("foo", "r")) == NULL) {
err(1, "failed after %d", i);
}
#else
if (open("foo", O_RDONLY) == -1) {
err(1, "failed after %d", i);
}
#endif
}
return 0;
}
如果您在将“#if 1”更改为“#if 0”的情况下运行此程序,它将按预期工作。看起来 MacOS 在 libc 中的 stdio 初始化期间读取了一次打开文件的限制,并且以后不再读取它们。您对 printf 的第一次调用会在 libc 中初始化 stdio,并缓存打开文件数的 rlimit 值。
在简单的“hello, world”上运行 dtruss 显示:
$ cat > hw.c
#include <stdio.h>
int main() { printf("hello, world\n"); return 0; }
$ cc -Wall -o hw hw.c && sudo dtruss ./hw 2>&1 | grep rlimit
getrlimit(0x1008, 0x7FFF58875AE8, 0x7FFF8BE92470) = 0 0
$
这表明事实确实如此。
虽然这是您应该与 Apple 联系的事情,但它闻起来像个错误。
关于c++ - printf 使 setrlimit 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17719715/