Чтобы полностью понять, что происходит, в первую очередь важно отметить, как ваша программа распределяет память.
Из вашего комментария у вас есть то, что для этого конкретного прогона память для buffer
начинается с 0x7fffffffdf10
, а затем modified
начинается с 0x7fffffffdf5c
(хотя randomize_va_space
может поддерживать это согласованным для всех прогонов,но я не совсем уверен).
Итак, у вас есть что-то вроде этого:
0x7fffffffdf10 0x7fffffffdf50 0x7fffffffdf5c
↓ ↓ ↓
(64 byte buffer)..........(some 12 bytes).....(modified)....
По сути, у вас есть буфер из 64 символов, затем, когда это заканчивается, есть 12 байтов, которыеиспользуется для некоторой другой переменной стека (вероятно, 4 байта argc
и 8 байтов для argv
), а затем модифицируется после, точно начиная с 64 + 12 = 76 байтов после запуска буфера.
Поэтому, когда вы записываете от 65 до 76 символов в 64-байтовый буфер, он проходит мимо и начинает запись в те 12 байтов, которые находятся между буфером и modified
.Когда вы начинаете писать 77-й символ, он начинает перезаписывать то, что в modified
, что заставляет вас видеть сообщение "you have changed the 'modified' variable
".
Вы также спросили "почему это работает, если я подхожу до 87 итогда на 88 есть segfault? Ответ в том, что, поскольку это неопределенное поведение, как только вы начнете запись в недействительную память и ядро распознает это, это немедленно убьет ваш процесс, потому что вы пытаетесь читать / записывать память, которую вы не 'у вас нет доступа к.
Обратите внимание, что на практике вы почти никогда не должны использовать gets
, и это серьезная причина, поскольку вы точно не знаете, сколько байтов вы будете читать, поэтому есть шанс перезаписатьТакже обратите внимание, что поведение, которое вы видите, не является тем же поведением, которое я наблюдаю на своей машине, когда я запускаю его. Это нормально, и это потому, что это неопределенное поведение. Нет никаких гарантий того, что произойдет, когда вы запустите его.На моей машине modified
на самом деле предшествует buffer
в памяти, поэтому я никогда не вижу, чтобы переменная modified
перезаписывалась,Я думаю, что это хороший учебный пример, чтобы понять, почему неопределенное поведение, подобное этому, просто непредсказуемо.