Ошибка сегментации * После * Ввод заканчивается, когда fgets () читает слишком много символов - PullRequest
0 голосов
/ 07 июня 2019

Я лаборант в своем университете для лабораторий информатики, и в течение первой недели обучения студент показал следующий код:

#include <stdio.h>
#include <stdlib.h>

static void copy (FILE *, FILE *);

int main (int argc, char *argv[])
{
    copy (stdin, stdout);
    return EXIT_SUCCESS;
}

static void copy (FILE *input, FILE *output)
{
    char c[2];
    while(fgets(c, 5, input) != NULL) {
        fputs(c, output);
    }
}

Код в приведенном выше примере работает так, как будто нет проблем с чтением пяти символов в массив символов размера 2, но затем приводит к ошибке сегментации после достижения EOF в stdin.

Мы узнали об использовании также видов функций ввода и вывода, и они обнаружили, что этот код обладает необычной функциональностью.

Вы ожидаете (или я так думаю) некоторой ошибки, когда fgets пытается прочитать больше символов в переменной 'c', чем у нее есть пробел.

Однако этот код работает полностью так, как можно было бы заподозрить в полностью функционирующей программе того же рода (повторяющиеся символы, набираемые при стандартном вводе), затем после segfaults после вводится символ EOF. Эту ошибку сегментации можно предотвратить, введя только n-2 или менее символов между каждой новой строкой, но в противном случае всегда срабатывает после того, как введен символ EOF (независимо от того, сколько строк было набрано ранее).

Почему это происходит? Похоже, что моя программа ждет до конца программы, чтобы сказать мне, что она имела ошибку сегментации двадцать строк ввода назад!

1 Ответ

3 голосов
/ 07 июня 2019

Это простой классический случай переполнения буфера из-за небрежного программирования.Переполнение буфера приводит к неопределенному поведению.

...
char c[2];                            // your declare your array with 2 elements
while(fgets(c, 5, input) != NULL) {   // but here you pretend it has 5 elements
    fputs(c, output);
...

Вы хотите это:

...
char c[2];   // btw 2 is execcsively small anyway
while(fgets(c, sizeof c, input) != NULL) {   // use correct size of c here
    fputs(c, output);
...

Неопределенное поведение означает именно то, что: поведение не определено, может произойти все, включая:

  • очевидно работает нормально
  • ошибка сегментации
  • неверный вывод данных
  • повреждение данных
  • зависание программы
  • другое ошибочное поведение
...