【问题标题】:Ctrl-D in input prints thousands of null characters输入中的 Ctrl-D 打印数千个空字符
【发布时间】:2021-12-26 09:24:47
【问题描述】:

我正在用 C 语言编写一个接受用户输入的程序,当我输入 Ctrl+d 时,它会打印数千个 (null) 作为输出。怎么了?是某种内存泄漏吗?代码如下:

while (1) {
    char *buffer = malloc(BUFFER_SIZE);
    fgets(buffer, BUFFER_SIZE, stdin);
    printf("%s", buffer);
  }

BUFFER_SIZE 设置为 256。

【问题讨论】:

    标签: c input


    【解决方案1】:

    是的,这可能是由于代码中的内存泄漏。您在循环的每一轮中分配一些内存,但您永远不会释放它。所以最终你会耗尽内存。

    首先malloc 每次返回一个新的 256 字节内存块。 fgets 从标准输入读取。由于用户按下了 Ctrl+D,标准输入为空,所以fgets 返回buffer 并且不写任何东西。 (fgets 不保证写入一个空字符串,即在buffer[0] 写入一个空字节,如果它没有读取任何内容。)然后printf 打印任何buffer 的内容是1 ,这可能是任何随机垃圾,并且可能由于内存未初始化而崩溃,并且不能保证缓冲区中有一个空字节来结束字符串。似是而非的,如果这是你的程序唯一做的事情,操作系统会为你的程序提供零填充内存,所以malloc 第一次使用特定的内存块时,它仍然用零填充,所以buffer是全字节零,它是一个空字符串,因此 printf 调用没有可见效果。

    最终malloc 内存不足,因此它返回NULL。使用空缓冲区调用 fgets 通常会导致分段错误1。但是,在fgets 看到空输入的特殊情况下,它可能根本不会尝试访问缓冲区,所以它只返回NULL。然后printf("%s", NULL),在您的平台上1,打印(null)

    解决办法是检查mallocfgets的返回值,释放你分配的内存。 (当然,您可以分配一次缓冲区并重用它,而不是在每次迭代时分配一个新缓冲区,但我假设这是一个学习练习或一个更复杂问题的简化。)

    while (1) {
        char *buffer = malloc(BUFFER_SIZE);
        if (buffer == NULL) {
            printf(stderr, "Out of memory\n");
            exit(EXIT_FAILURE);
        }
        if (fgets(buffer, BUFFER_SIZE, stdin) == NULL) break;
        printf("%s", buffer);
        free(buffer);
    }
    

    1通常,在 C 中,这具有未定义的行为。我正在描述在 Ctrl+D 是标准键绑定以指示用户输入结束的平台上的可能行为。

    【讨论】:

    • 仅供参考,Control-D does not indicate the end of user input; it merely transmits the currently queued characters to the foreground process。当传输包含零个字符时,其他软件将其解释为 EOF。例如,如果您键入多个字符,然后按 control-D,则字符将正常处理并且不会报告 EOF。如果您在行首按 control-D,当没有字符待处理时,其他软件会报告 EOF。或者,如果您按两次 control-D,第二次会导致 EOF。
    • @EricPostpischil 是的,但是在这个问题的上下文中,表示输入结束的行首的 Ctrl+D 是唯一相关的方面。
    • 在人们的头脑中植入错误的想法会导致更多的工作,因为纠正错误的想法并教授正确的想法比一开始就正确地教授它们更难。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    • 2022-01-18
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2018-04-22
    • 1970-01-01
    相关资源
    最近更新 更多