Доступ за пределами элементов динамически распределенных массивов / без SegFault - PullRequest
1 голос
/ 19 октября 2011

Я разрабатываю программу на C, которая использует массив связанных списков (примитивная хэш-таблица) в качестве типа данных для представления определенной информации о дате.Массив состоит из двенадцати элементов, соответствующих месяцам года, и каждый месяц имеет связанный список, содержащий узлы данных.

Я разработал модуль, который использовал этот тип данных, и он работал нормально.Позже я обнаружил, что у меня есть доступ к элементам массива, которые находятся за пределами (например, доступ к 12-му элементу по индексу 12 вместо 11).Но программа работала последовательно, без инцидентов.Я никогда не получал ошибку сегментации.С тех пор я исправил ошибку кодирования.Кто-нибудь может объяснить, почему доступ к внешним элементам не приведет к segfault?

Это не первый раз, когда это происходит.Я создал динамически размещаемый многомерный массив, и для тестирования я попытался получить доступ к элементам за пределами.Программа работала нормально, давала точные результаты и в большинстве случаев не вызывала ошибок.Единственный раз, когда я его достиг, мне пришлось попытаться получить доступ к элементам, находящимся за пределами границ.

(Эти программы в настоящее время являются приложениями консоли Windows для тестирования. Я компилирую с MinGW. Я могу включить код, если онбыло бы полезно.)

Ответы [ 4 ]

4 голосов
/ 19 октября 2011

В C доступ к массиву вне его границ - это неопределенное поведение .

Это означает, что может произойти что угодно , включая программу, которая ведет себя так, как вы этого ожидаетеto.

Язык C не требует проверки границ при доступе к массиву, и большинство компиляторов C не реализуют его.

Например, предположим, что вы объявляете:

int before;
int array[10];
int after;

Порядок, в котором они хранятся в памяти, не определен, но предположим, что они хранятся непрерывно в том порядке, в котором они объявлены.Если вы попытаетесь получить доступ к array[-1], вы можете получить доступ к before.Если вы попытаетесь получить доступ к array[10], вместо этого вы можете получить доступ к after.

На программиста ложится бремя избегать доступа к массивам за их пределами.Или не может быть ничего выделено до и / или после вашего массива.

Аналогия: «Знак говорит, что мне разрешено переходить улицу только тогда, когда свет зеленый. Я пересек красный и ничегослучилось. Почему машина не ударила меня? "(Есть языки, которые делают все возможное, чтобы заставить машину сбить вас. C не один из них.)

1 голос
/ 19 октября 2011

Доступ к данным путем индексации за пределами массива - неопределенное поведение.В большинстве случаев (в частности, динамически выделяемая память) при доступе к данным «рядом» (не слишком далеко за пределами) массив не будет зависать по разным причинам.Память может быть выделена в виде округленных кусков, больше, чем вы запрашивали, или реализация «malloc» может поместить некоторую произвольную бухгалтерскую информацию и т. Д. Конечным результатом является то, что этот фрагмент памяти отображается, хотя может содержать данные в диапазоне от мусора до важного бронирования.хранение информации.Не полагайтесь на это поведение.

1 голос
/ 19 октября 2011

SegFaults - существа ОС.Они выбрасываются, когда процесс пытается получить доступ к памяти, которая ему не принадлежит и не является частью языка Си.В C доступ к элементам за пределами является просто неопределенным поведением, что означает, что он может потерпеть неудачу, а может и нет.Если, например, распределитель памяти предоставил кусок памяти больше, чем вы запрашивали для массива, ОС не будет беспокоиться, если вы выйдете за пределы допустимого, потому что вы будете обращаться к памяти, которая принадлежит вашему процессу,В этом случае вы просто получаете ошибку в вашей программе.

1 голос
/ 19 октября 2011

Не мог бы кто-нибудь объяснить, почему доступ к элементам, выходящим за пределы, не приведет к segfault?

Это неопределенное поведение, оно не должно быть segfault.В Linux вы можете запустить свою программу под Valgrind, чтобы перехватить ошибки такого рода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...