int p;
int i1;
int i2;
i1 = 1 << 16;
i2 = 1 << 8;
p = int(&i1)+3;
cout << hex;
cout << "&i1: " << int(&i1) << endl;
cout << "&i2: " << int(&i2) << endl;
for(int i = 0; i < 16; i++)
cout << p << ": " << uint(*((byte*)p--)) << endl;
Выход:
&i1: 12fac8 &i2: 12fabc 12facb: 0 12faca: 1 12fac9: 0 12fac8: 0 12fac7: cc 12fac6: cc 12fac5: cc 12fac4: cc 12fac3: cc 12fac2: cc 12fac1: cc 12fac0: cc 12fabf: 0 12fabe: 0 12fabd: 1 12fabc: 0
Я использую 32-битную Windows 7, использую Visual Studio 2010. Больше нечего сказать, но stackoverflow не позволит мне публиковать без дополнительных «подробностей», так что это просто бесполезная болтовня 🙂
Когда вы компилируете код в Visual C с /GZ
опция, все неинициализированные переменные стека устанавливаются с помощью 0xcc
шаблон (чтобы помочь отладке, я подозреваю).
Следовательно, эти байты, вероятно, p
а также i
целые (А), или временные, созданные эксцентричный метод использования int
как указатель, то, что вы можете переосмыслить.
В любом случае, Зачем они там не имеют значения на вашем конкретном уровне абстракции, C ++ «виртуальная машина». Реализация свободна организовать стек так, как она хочет для эффективности, вставляя отступ там, где это необходимо.
(А) Несмотря на i
позже объявлено в коде, ничто не мешает установке выделить пространство для него при входе в функцию. Большинство вещей, происходящих под прикрытием, могут удивлять, как это, так как правило «как будто» определяет, как работает реализация. Он может делать все, что захочет, при условии эффект соответствует тому, что в стандарте.
0xcc появляется при запуске в отладочной сборке. Это сделано потому, что вы можете легко распознать этот шаблон, когда вы ищете ошибки для переполнения буфера и т. Д.
Это либо заполнение, либо неиспользуемые временные переменные. В MSVC с отладочными сборками компилятор генерирует код для заполнения всех переменных 0xcc
байт. Это помогает идентифицировать неиспользуемые переменные — и выбор cc
это не случайный выбор, это помогает, потому что это почти невозможно получить адрес от ОС, и это также int 3
инструкции, поэтому, если вы вдруг найдете способ выполнить этот код (например, указатель на функцию где-то в данных), код будет остановлен тут же. Отладив несколько проблем с «убегающим кодом», я нахожу это очень полезной функцией.
Тот факт, что это довольно высокое (или отрицательное) число, также полезен, поскольку он часто демонстрирует «использование переменной в качестве индекса или указателя», делая ее недопустимым доступом, а не, скажем, если бы это был ноль, который был бы допустимый индекс в массив, например.