【问题标题】:printf makes setrlimit not workingprintf 使 setrlimit 不起作用
【发布时间】:2013-07-18 09:33:57
【问题描述】:

特别是在 SO questionthis 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。

【问题讨论】:

  • 1.您的代码与输出不匹配。 2. 我刚刚在 Red Hat 5 系统上试了一下,得到了相同的数字,有和没有“Hello”。我相信这也将取决于您系统上的其他情况。
  • 这是我正在使用的确切代码。我在 Mac OS 10.7 和 Xcode 4.6.2 上,也许这就是原因。
  • 真的吗?您正在使用的确切代码包含printf("after..."),但打印出"limit ..."?您的 printf 实现严重损坏!
  • 对不起,我没有看到这个错字,谢谢你指点我。但这并没有改变任何问题。
  • 这很重要。您应该始终发布您发布的确切代码的输出。人们应该如何猜测您发布的代码和您运行的代码之间的差异?但无论如何,这些结果是否可以反复重现?我感觉您的结果取决于系统上其他程序中打开了多少文件。我希望肯定知道的人会在这里插话,只是想推动更多有用的信息,因为没有其他人在说什么。

标签: c++ c printf setrlimit


【解决方案1】:

这是一个更好的程序版本,展示了问题的更多方面。

#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 值。

在微不足道的“你好,世界”节目上运行 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 的东西,它闻起来像一个 bug。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 2017-04-05
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-11
    相关资源
    最近更新 更多