Сбой происходит из-за того, что ваше объявление переменной 'p' выделяет в вашем стеке только достаточно места для одного (int *) указателя, но затем вы помещаете значения в (& p + 2) и т. Д.-knows-что.Он ведет себя по-разному с GDB или без него, потому что часть «кто знает, что» может быть не критичной в одной среде, но критичной в другой.
Возможно, вы сможете «исправить» свою программу, убедившись, чтопространство, которое вы собираетесь выбросить, не является чем-то критичным.
int main(){
int* p;
char junk[100]; /* ADD THIS */
Теперь пространство, следующее за хранилищем, выделенным для 'p', (скорее всего) будет массивом мусорных символов, который вы можете получитьперезаписать(По крайней мере, это «исправляет» программу в моей конкретной системе Linux, когда я компилирую с помощью «gcc -O0 -g»).
Все, что сказано - метод, который вы там используете, отсутствует в любомспособ портативный или безопасный.Компилятор не дает никаких обещаний, что он собирается расположить хранилища в определенном порядке, в котором мы их объявляем.Кроме того, компиляция с различными ключами оптимизации может изменить поведение.Так что, хотя это может быть интересным упражнением, вы не должны ожидать, что этот метод будет работать согласованно.
Ручное манипулирование стеком C таким способом - ПЛОХАЯ ИДЕЯ!