2012-02-17 7 views
1

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

#include <stdio.h> 

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

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

grep ....| a.out

или

echo ....| a.out

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

ответ

0

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

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

scanf("%1023s", buf); 

и не для обеспечения стека не перерасход на использование Printf MemSet:

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; 
} 
+0

memset не требуется, так как мы можем легко инициализировать массивы 0 в C99-C11. Это также, вероятно, быстрее, но это зависит от реализации системы. – AoeAoe

+1

@thlgood: Почему это принятый ответ? Это явно не отвечало на вопрос, тогда как я нашел проблему. –

7

Все, что вы эхо или grepping должно содержать более 1023 символов. (1024 - 1 для нулевого терминатора.)

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

Учитывая ваш тестовый ввод, вы не должны получать segfault. Я просто попробовал его на местном уровне, и он работал нормально. Если вы находитесь на Linux, так как вы написали a.out вместо ./a.out, в зависимости от того, как ваш путь настроен вы можете запустить неправильную программу

+0

no..I запустить 'echo 'Это' | a.out', он по-прежнему получил« Ошибка сегментации » – thlgood

+1

Я просто попробовал и не получил ошибку сегментации. –

+0

'fscanf' не обеспечивает больше защиты, чем' scanf', это просто 'scanf', используя явный дескриптор файла, а не' stdin' - я думаю, вы имели в виду 'fgets', у которого _does_ есть предел для прочитанных символов. – paxdiablo

2

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

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

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

без необходимости писать свой собственный инструмент, чтобы сделать работу. Фактически, с sed, awk и понравившимся вам, вы, вероятно, never нужно написать инструменты для обработки текста самостоятельно.

Смежные вопросы