Ошибка сегментации только при перенаправлении stdout на /dev/null?

У меня есть модульный тест С++, который выводит полезный вывод на стандартный вывод и в основном шум (если я не отлаживаю) на стандартный вывод, поэтому я хотел бы перенаправить стандартный вывод на /dev/null.

Как ни странно, это, по-видимому, вызывает ошибку сегментации.

Есть ли какая-либо причина, по которой код может ошибаться с ошибкой «> /dev/null» и в противном случае работать нормально?

Вывод производится полностью printfs, если это имеет какое-либо значение.

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

после смерти

Segfault был вызван таким кодом:

ArrayElt* array = AllocateArrayOfSize(array_size);
int index = GetIndex(..) % array_size;
ArrayElt elt = array[index];

В сотый раз я забыл, что x % y остается отрицательным, когда x отрицательное в C/C++.

Итак, почему это происходило только тогда, когда я перенаправлялся на /dev/null? Я предполагаю, что неверный адрес памяти, к которому я обращался, находился в выходном буфере для стандартного вывода, и этот буфер не выделяется, когда он не нужен.

Спасибо за хорошие ответы!


person Tyler    schedule 11.10.2009    source источник
comment
Является ли код многопоточным? Если это так, возможно, что перенаправление stdout может изменить время критического аспекта вашей программы и вызвать ошибку состояния гонки.   -  person bcat    schedule 11.10.2009
comment
Не многопоточный. Как запустить gdb в процессе с перенаправленным выводом? gdb ./mybinary › /dev/null также перенаправляет стандартный вывод gdb.   -  person Tyler    schedule 11.10.2009
comment
Знак x % y, когда любой операнд отрицателен, определяется реализацией, поэтому вы не можете переносимо полагаться на наблюдаемое поведение.   -  person CB Bailey    schedule 11.10.2009
comment
@Tyler: если вы пришли из страны LISP или откуда-то еще, где требуется (x mod y) для возврата положительного числа, то, возможно, вам следует написать себе функцию (шаблон?), которая сделает всю работу за вас, и использовать ее вместо Оператор? Целочисленная версия проста; вам, вероятно, потребуется предоставить одну или несколько специализаций для чисел с плавающей запятой.   -  person Jonathan Leffler    schedule 11.10.2009


Ответы (3)


Нет «нормальной» причины для ввода-вывода в стандартный вывод для запуска дампа ядра, когда стандартный вывод перенаправляется на /dev/null.

Скорее всего, у вас есть блуждающий указатель или переполнение буфера, которое запускает дамп ядра при отправке в /dev/null, а не при отправке в стандартный вывод, но без кода будет сложно обнаружить проблему.

Принято помещать полезную информацию в стандартный вывод, а шум — в стандартную ошибку.

person Jonathan Leffler    schedule 11.10.2009

Это не совсем ответ на ваш вопрос, но может. Пробовали ли вы использовать gdb? Это инструмент отладки командной строки, который может найти, где происходят ошибки сегментации. Его довольно легко использовать. Вот подробное руководство по его использованию.

person Kredns    schedule 11.10.2009
comment
Хорошая идея - я использовал это немного раньше. Когда я запускаю gdb ./my_binary › /dev/null, я также теряю интерфейс для gdb — как я могу запустить gdb в моем процессе с перенаправлением его стандартного вывода? - person Tyler; 11.10.2009
comment
@Tyler: проверьте параметры запуска в пределах gdb: gdb ./my_binary в командной строке (или добавьте имя дампа ядра, если он у вас есть), а затем запустите программу с помощью «run ›/dev/null». - person Jonathan Leffler; 11.10.2009

Возможно, что-то проверяет "isatty", что может привести к другому поведению /dev/null.

Возможно, что-то читает из стандартного вывода, что не удастся для /dev/null.

person Martin v. Löwis    schedule 11.10.2009
comment
@Martin: если /dev/null открыт для чтения, то вы можете читать из него (но вы не получаете никакой информации - только «EOF»). Если кто-то ожидает чтения из канала, номинально доступного только для записи (то есть код читается из стандартного вывода), то у него серьезные проблемы (но часто это может сойти с рук, когда стандартный вывод является терминалом). - person Jonathan Leffler; 11.10.2009