Возможный дубликат:
Переполнение массива (почему это работает?)
Я нашел код C ++, который делает что-то вроде этого:
struct Test
{
int a[128];
char b[768];
};
int main()
{
Test test;
for( int i = 0; i < 200; ++i)
test.a[i] = 1;
return 0;
}
Я понимаю, что это неправильно. Но я хочу знать, какой будет эффект?
На GCC 4.3.4 массив Test :: b остается нетронутым. Это гарантировано? Что здесь происходит?
Это тот же эффект для чтения? например
int main()
{
Test test;
for( int i = 0; i < 200; ++i)
int z = test.a[i];
return 0;
}
Это неопределенное поведение, и что-нибудь может случиться.
Здесь нужно учитывать гораздо больше переменных, чем просто компилятор — версия, ОС, аппаратное обеспечение, погода, какой день недели и т. Д.
Стандарт гласит, что неопределенное поведение может означать что угодно, поэтому у вас не может быть никаких ожиданий, даже с одним и тем же компилятором.
Если, например, у вас была другая переменная, расположенная сразу после test.a
Вы можете получить нарушение прав доступа. Или вы можете просто перезаписать эту переменную. Все идет.
По сути, в данном случае не часть записи, а вызов
test.a[i]
с i>=128
, Это просто не разрешено.
это undefined behaviour
Вы не можете предсказать, что будет, если вы будете писать за пределами массива.
Неопределенное поведение. Нет абсолютно никаких гарантий, и буквально все может случиться. Распространенное капризное замечание заключается в том, что он может послать козлу по электронной почте вашей бабушке.
http://en.wikipedia.org/wiki/Undefined_behavior
На практике это, вероятно, продолжит писать дальше в Test
объект, хотя начало b
может не следовать сразу после окончания a
из-за заполнения для выравнивания.
В C ++, абстрактном языке, определенном стандартом C ++, может случиться что угодно.
В G ++ 4.3.4 конкретный язык, определенный этим компилятором, конкретный что-нибудь что произойдет, вы перезапишете первые 288 элементов test.b
,
Помимо «неопределенного поведения», то, что действительно происходит, зависит от того, используется ли фактически перезаписываемая часть или нет. Если этот фрагмент памяти не используется, это может вызвать ошибку или сбой (в зависимости от того, выполняете ли вы какие-либо действия для отслеживания проблемы). Однако, если там есть какие-то данные и они не аварийно завершают работу, это может вызвать каскадный эффект в вашем программном обеспечении, когда другой фрагмент кода, который зависит от перезаписанной части, не может быть выполнен. Это то, что делает отслеживание этих проблем настолько сложным, поскольку при сбое в каскаде трудно найти основную причину, а не видимые симптомы («Почему эта переменная имеет значение x, когда я никогда не назначаю такого рода значение для нее» «)