Утечки памяти с помощью kbhit для Linux - PullRequest
0 голосов
/ 18 февраля 2019

Код здесь .Когда я запускаю свою программу (я сохранил kbhit как файл заголовка и сохранил его в папке с моей программой), я получаю неинициализированный доступ на чтение при первом использовании kbhit (я использую DrMemory для отладки памяти).Я включил sys / ioctl.h, так как моя программа не могла использовать FIONREAD без него.Проблема, которая возникает, - это вызов tcsetattr (STDIN, TCSANOW, & term);Я не совсем понимаю, как это работает, поэтому любая помощь будет оценена.Спасибо!

Редактировать: точное сообщение: «UNINITIALIZED READ: чтение 12 байтов.системный вызов ioctl.0x5402, параметр № 2 ». Строка относится к вызову tcsetattr ().Эта ошибка возникает после сохранения kbhit в виде cpp-файла и его преобразования в другой файл.Программа работает нормально, за исключением одной ошибки.

1 Ответ

0 голосов
/ 18 февраля 2019

Вот версия кода, которую я изменил, чтобы она была реальным C, а не C ++, поскольку это был C ++ из-за небрежности с ключевыми словами bool true / false и struct.

И, о да, донне помещайте это в заголовочный файл.Поместите его в файл с именем kbhit.c и удалите или закомментируйте основную функцию теста.А в заголовочном файле просто напишите строку:

int _kbhit(void);

Или вам может понадобиться:

extern "C" int _kbhit(void);

Это все, что вам нужно в заголовке.

/**
 Linux (POSIX) implementation of _kbhit().
 Morgan McGuire, morgan@cs.brown.edu
 */
#include <stdbool.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>

int _kbhit(void) {
        static bool initialized = false;

        if (! initialized) {
                // Use termios to turn off line buffering
                struct termios term;
                tcgetattr(STDIN_FILENO, &term);
                term.c_lflag &= ~ICANON;
                tcsetattr(STDIN_FILENO, TCSANOW, &term);
                setbuf(stdin, NULL);
                initialized = true;
        }

        int bytesWaiting;
        ioctl(STDIN_FILENO, FIONREAD, &bytesWaiting);
        return bytesWaiting;
}

//////////////////////////////////////////////
//      Simple demo of _kbhit()

int main() {
        printf("Press any key");
        while (! _kbhit()) {
                printf(".");
                fflush(stdout);
                usleep(1000);
        }
        printf("\nDone.\n");

        return 0;
}

Это выглядит правильно для меня, и Вальгринд не жалуется.У меня нет доктора Памяти.

Принцип работы этого кода заключается в том, что он сначала использует tcgetattr для чтения структуры termios (настройки вывода терминала, я думаю).Затем он изменяет его, сбрасывая биты ICANON.Canon - это каноническая настройка для терминалов, которая включает буферизацию строки.Затем он записывает новые значения termios обратно в терминал.с tcsetattr.

Вызов ioctl получает количество байтов, ожидающих в буфере.Если ожидают байты, то кто-то нажал какие-то клавиши.

...