Проблема замещения процесса в оболочке GDB - PullRequest
2 голосов
/ 06 ноября 2019

Следующий код, readTwice.c , читает со стандартного ввода дважды:

int main()
{
    char s[8]={0};
    read(0, (void *)s, (size_t) 3);
    read(0, (void *)(s + 4), (size_t) 3);
    for (int i = 0; i < 8; i++)
        printf("%d: 0x%x\n", i, s[i]);
    return 0;
}

Моя цель состоит в том, чтобы при отладке соответствующего двоичного файла передать первому read ()первый файл a (скажем, созданный echo a > a) и второй файл read () со вторым файлом b (скажем, созданный echo b > b).

За пределами GDB следующая команда bash 5.0 дает желаемый эффект:

$ ./readTwice < <(cat a;cat b)
0: 0x61
1: 0xa
2: 0x0
3: 0x0
4: 0x62
5: 0xa
6: 0x0
7: 0x0

Однако при запуске двоичного файла в GDB 8.2.1 с тем же перенаправлением процесса первый вызов read () также читаетначало второго файла:

$ gdb -q readTwice
Reading symbols from readTwice...(no debugging symbols found)...done.
(gdb) run < <(cat a;cat b)
Starting program: /home/av/root-me/ch77/readTwice < <(cat a;cat b)
0: 0x61
1: 0xa
2: 0x62
3: 0x0
4: 0xa
5: 0x0
6: 0x0
7: 0x0
[Inferior 1 (process 4710) exited normally]
(gdb) 

Не могли бы вы помочь мне понять это поведение и / или рассказать мне о команде, имеющей желаемый эффект?

1 Ответ

0 голосов
/ 06 ноября 2019

Вход в вашу программу состоит из 4 символов:

'a' '\n' 'b' '\n'

Внутри вашей программы вы используете два reads:

read(0, (void *)s, (size_t) 3);
read(0, (void *)(s + 4), (size_t) 3);

read не читается точно 3 символов. Он читает до 3 символов и возвращает количество прочитанных символов, см. man read (2) . Я предполагаю, что по умолчанию STDIN_FILENO блокирует на вашей платформе, поэтому он должен прочитать как минимум 1 символ.

Возможные результаты:

  • Оба read s читают 1 байт. s будет иметь {'a',0,0,0,'\n',0,0,0}. На входе есть 2 непрочитанных байта.
  • Первый read читает 1 байт, второй читает 3 байта. s будет иметь {'a',0,0,0,'\n','b','\n',0}
  • Первый read читает 3 байта, второй читает 1 байт. s будет иметь {'a','\n','b',0,'\n',0,0,0}. Это вывод, который вы наблюдаете в gdb.
  • Первый read читает 2 байта, второй читает 2 байта. s будет иметь {'a','\n',0,0,'b','\n',0,0}. Это вывод, который вы наблюдаете при запуске в оболочке.
  • Надеюсь, вы уже поняли идею.

Скорее всего, ваша операционная система реализует read на STDIN_FILENO в строкебуферизованная мода на вашей платформе, поэтому вы можете наблюдать два наиболее вероятных результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...