Я не удивлен недостатком памяти. Программа not разыменовывает неинициализированный указатель. Вместо этого он копирует и печатает содержимое памяти, начинающуюся с переменной указателя, и 996 (или 992) байта за ней.
Поскольку указатель представляет собой стекную переменную, он печатает память вверху стека для путей вниз. Эта память содержит фрейм стека main()
: возможно, некоторые сохраненные значения регистра, количество аргументов программы, указатель на аргументы программы, указатель на список переменных окружения и сохраненный регистр команд для main()
для возврата , обычно в стартовом коде библиотеки времени выполнения C. Во всех реализациях, которые я исследовал, ниже представлены стековые кадры, которые имеют копии самих переменных среды, массив указателей на них и массив указателей на аргументы программы. В средах Unix (которые вы намекаете, что используете) строки аргументов программы будут ниже этого.
Вся эта память «безопасна» для печати, за исключением некоторых непечатаемых символов, которые могут испортиться терминал [. g9]
. Основная потенциальная проблема заключается в том, достаточно ли выделенной и сопоставленной памяти стека, чтобы предотвратить SIGSEGV во время доступа. Ошибка сегмента может произойти, если слишком мало данных о среде. Или если реализация помещает эти данные в другое место, так что здесь всего несколько слов стека. Я предлагаю подтвердить, что очистка переменных окружения и повторное выполнение программы.
Этот код не был бы настолько безвредным, если какая-либо из конвенций времени выполнения C не соответствует истине:
void *x
) выделяется в стеке main()
с аргументами. (Некоторые среды с низкой нагрузкой, такие как встроенные процессоры, вызывают main()
без параметров.) Во всех основных современных реализациях все они в целом верны.