输入中的 Ctrl-D 打印数千个空字符

Ctrl-D in input prints thousands of null characters

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

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

BUFFER_SIZE 设置为 256。

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

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

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

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

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 是标准键绑定以指示用户输入结束。