Что происходит, когда вы пишете в память за пределами массива?

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

Вот программа, о которой идет речь, комментарии – мои заметки:

#include  #define MAX 4 void RecordArgs(int x); int main() { RecordArgs(1); RecordArgs(7); RecordArgs(-11); return 0; } void RecordArgs(int x) { static int i = 0; int call_count = 0; int arg_history[MAX] = {0}; if (call_count == MAX) { # call_count is not static and is initialized to 0 on each call # as a result, under no circumstance can call_count == MAX and # this printf is never executed printf("Too many calls to RecordArgs\n"); } else { # index out of bounds on second/third call (i + call_count will be 4??) arg_history[i + call_count] = x; ++call_count; ++i; for (i = 0; i < MAX; ++i) printf("%d ", arg_history[i]); printf("\n"); } } 

И ожидаемый результат:

 1 0 0 0 0 0 0 0 0 0 0 0 

Когда RecordArgs вызывается вторым и третьим раза, где записываются значения 7 и -11? Я попробовал скомпилировать его в разных настройках, чтобы увидеть, могу ли я написать две записи, но не все, что я пробовал, привело к тому, что точный вывод без каких-либо segfaults.

Расширяя комментарий Patashu, ошибки сегментации возникают, когда вы получаете доступ к памяти со страницы таким образом, который сталкивается со страницей разрешений на память. Другими словами, они возникают, когда вы получаете доступ к странице памяти так, как вам не разрешено. Возможно, что в вашей ситуации происходит то, что вы обращаетесь к памяти еще на той же странице, на которой хранится arg_history , для которой у вас, очевидно, есть разрешение читать и писать.

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

В любом случае это неопределенное поведение в C. Хотя вы видите «ожидаемые результаты», это не должно указывать на то, что программа верна. Фактически, это обстоятельство, в котором ошибка вне границ может потенциально остаться незамеченной, если она не вызывает ошибку сегментации.