- Являются ли ВСЕ segfaults неопределенным поведением?
Этот вопрос сложнее, чем может показаться, потому что "неопределенное поведение" является описанием любой исходной программы на Cили результат запуска C-программы на «абстрактной машине», которая описывает поведение C-программ в целом;но «ошибка сегментации» - это возможное поведение конкретной операционной системы, часто с помощью определенных функций ЦП.
Стандарт C ничего не говорит о сбоях сегментации.Одна почти уместная вещь, которую он говорит, это то, что если выполнение программы не имеет неопределенного поведения, то выполнение программы в реальной реализации будет иметь такое же наблюдаемое поведение, как и выполнение абстрактной машины.А «наблюдаемое поведение» определено так, чтобы включать в себя только доступ к изменчивым объектам, данные, записанные в файлы, а также ввод и вывод интерактивных устройств.
Если мы можем предположить, что «ошибка сегментации» всегда предотвращает дальнейшие действия со стороныПрограмма, то любая ошибка сегментации без присутствия неопределенного поведения может произойти только после того, как все наблюдаемое поведение завершится, как ожидалось.(Но обратите внимание, что действительные оптимизации могут иногда приводить к тому, что вещи происходят в порядке, отличном от очевидного.)
Таким образом, ситуация, когда программа вызывает ошибку сегментации (для ОС), хотя нет неопределенного поведения (согласно стандарту C) не имеет особого смысла для реального компилятора и ОС, но мы не можем полностью исключить это.
Но также и все, что предполагает идеальные компьютеры.Если оперативная память плохая, предполагаемое значение адреса может измениться.Есть даже очень редкие, но измеримые события, когда космические лучи могут немного измениться в остальном хорошей оперативной памяти.Мягкие ошибки, подобные этим, могут вызвать ошибку сегментации (в системе, где «ошибка сегментации» - вещь), практически для любой прекрасно написанной программы на С, без какого-либо неопределенного поведения, возможного для любой реализации или ввода.
Если нет, то есть ли способ обеспечить защиту от ошибок?
Это зависит от контекста и того, что вы подразумеваете под "обеспечить".
Можете ли вынаписать программу на C, которая всегда вызывает segfault?Нет, потому что некоторые компьютеры могут даже не иметь такой концепции.
Можете ли вы написать программу на C, которая всегда вызывает segfault, если это возможно на компьютере?Нет, потому что некоторые компиляторы могут делать что-то, чтобы избежать реальной проблемы в некоторых случаях.А поскольку поведение программы не определено, то, что не вызывает segfault, является таким же допустимым результатом, как и причина segfault.В частности, одно реальное препятствие, с которым вы можете столкнуться, выполняя даже такие простые вещи, как намеренное разыменование значения нулевого указателя, заключается в том, что при оптимизации компилятора иногда предполагается, что входные данные и логика всегда будут работать так, что неопределенное поведение не произойдет, так как это нормальноне делайте то, что программа говорит для входов, которые приводят к неопределенному поведению.
Зная подробности о том, как одна конкретная ОС, и, возможно, ЦП, обрабатывает память и иногда генерирует ошибки сегментации, вы можете написать инструкции по сборке, которые всегда будутвызвать segfault?Конечно, если обработка segfault имеет какое-либо значение вообще.Можете ли вы написать программу на C, которая будет вызывать segfault примерно таким же образом?Скорее всего.