Ошибка сегментации в трубе - PullRequest
1 голос
/ 17 февраля 2012

Учитывая следующую программу:

#include <stdio.h>

int main()
{
    char buf[1024];
    scanf("%s", buf);
    printf("----> %s", buf);
    return 0;
}

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

grep ....| a.out

или

echo ....| a.out

Я получаю Segmentation fault ошибку. Кто-нибудь может объяснить, почему?

Ответы [ 3 ]

7 голосов
/ 17 февраля 2012

Независимо от того, что вы повторяете, или восклицание должно содержать более 1023 символов. (1024 - 1 для нулевого терминатора.)

Вместо scanf используйте fgets и укажите размер. Либо используйте scanf, но укажите длину поля. Вы можете сделать scanf("%1023s", buf);. Если доступно больше байтов, вы всегда можете сделать это снова, чтобы прочитать остальные.

Учитывая ваш тестовый ввод, вы не должны получать сообщение об ошибке. Я только попробовал это локально, и это работало отлично. Если вы работаете в Linux, так как вы написали a.out вместо ./a.out, в зависимости от того, как настроен ваш путь, вы можете запустить не ту программу (что-то вроде a.out в папке bin?)

2 голосов
/ 17 февраля 2012

Никогда не используйте scanf с неограниченными строками.fgets предоставляет гораздо более безопасную альтернативу, особенно если вы предоставляете интеллектуальную функцию-оболочку, такую ​​как в этот ответ .

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

WhateverYourCommandIs | sed 's/^/----> '

без необходимости писать собственный инструмент для выполнения этой работы.На самом деле, с sed, awk и подобными вам, вероятно, никогда не нужно писать инструменты для обработки текста самостоятельно.

0 голосов
/ 17 февраля 2012

из scanf man:
s Соответствует последовательности символов, не являющихся пробелами;следующий указатель должен быть указателем на массив символов, который достаточно длинный, чтобы содержать входную последовательность и завершающий нулевой символ ('\ 0'), который добавляется автоматически.Входная строка останавливается на пустом месте или на максимальной ширине поля, в зависимости от того, что произойдет раньше.

указание максимальной ширины поля предотвратит переполнение стека

    scanf("%1023s", buf);

и обеспечит переполнение стека при использовании printfmemset:

    memset(buf,0,1024);

, поэтому программа будет:

#include <stdio.h>
#include <string.h>
int main()
{
    char buf[1024];
    memset(buf,0,1024);
    scanf("%1023s", buf);
    printf("----> %s", buf);
    return 0;
}
...