C ++ стек и повреждение кучи

Я недавно читал о стеке & повреждение кучи в C & C ++. Автор сайта демонстрирует повреждение стека, используя приведенный ниже пример.

#include<stdio.h>
int main(void)
{
int b = 10;
int a[3];
a[0] = 1;
a[1] = 2;
a[2] = 3;

printf(" b = %d \n",b);
a[3] = 12; // oops it is invalid, behaviour is undefined
printf(" b = %d \n",b);
printf("address of b= %x\n",&b);
printf("address of a[3]= %x\n",&a[3]);
return 0;
}

Я тестировал выше программу на компиляторе Visual Studio 2010 (VC ++) & это дает мне ошибку во время выполнения, которая говорит:

стек вокруг переменной а повреждается

Теперь мой вопрос: поврежден ли стек на всю жизнь или только на время, когда выполнялась ошибочная программа?

Точно так же я знаю, что удаление одного и того же указателя дважды может привести к очень плохим вещам, таким как повреждение кучи.
Следующий код:

int* p=new int();
delete p;
delete p;  // oops disaster here, undefined behaviour

Когда вышеупомянутый фрагмент кода выполняется, VC ++ показывает ошибку повреждения кучи во время выполнения.

3

Решение

Вы должны быть осторожны с терминологией здесь. Будет ли стек «поврежден» до конца жизни вашей программы? Это может быть; а может и не быть. В этом случае вы только повредили данные в текущем кадре стека, поэтому, как только вы выйдете из этого вызова функции, на практике ваше «повреждение» исчезнет.

Но это еще не все. Поскольку вы перезаписали переменную байтами, которых там не должно быть, какие эффекты могут повлиять на вашу программу? Последствия повреждения памяти могут быть логически передается другим областям функций или даже другим компьютерам, если вы отправляете эти данные по сетевому соединению и данные больше не находятся в ожидаемой форме. (Как правило, в ваш протокол данных встроены функции безопасности для обнаружения и удаления неожиданных форм данных; но это зависит от вас.)

То же самое верно и в отношении кучи коррупции. Каждый раз, когда вы перезаписываете байты чего-то, что не должно быть перезаписано, и каждый раз, когда вы делаете это с произвольный или же непостижимый данные, вы рискуете получить потенциально катастрофические последствия, которые могут логически длиться гораздо дольше, чем время жизни вашей программы.

В рамках языка Си ++ как языка это условие суммируется в определенной фразе: неопределенное поведение. В нем говорится, что вы действительно не можете на что-либо положиться после того, как испортили свою память. После того, как вы активировали UB, все ставки отменены.

Единственная гарантия, которую вы обычно имеете на практике, заключается в том, что ваша ОС не позволит вам напрямую перезаписывать память, которая не принадлежит вашей программе. То есть повредить память других процессов или самой ОС очень сложно. Модель памяти современных ОС специально спроектирована таким образом, чтобы сохранять программы изолированными и предотвращать такого рода повреждения от сломанных программ и / или вирусов.

6

Другие решения

это Неопределенное поведение. Вы не можете знать, что произойдет, если вы будете делать «запретные» вещи. У вас нет гарантии, что ваша программа будет работать хорошо.

7

В C ++, как и в C, нет переполнения границ массива или проверки недостаточности. Однако вы можете абстрагироваться, вы можете определить массив с перегруженным индексным оператором (operator []), где вы можете проверять индекс массива вне границ и действовать соответственно. Когда вы удаляете указатель, используя delete ptr (когда ptr выделяется через new), пространство, выделенное ранее, возвращается обратно в пространство кучи, однако значение указателя становится таким же, как и раньше. Итак, это хорошая практика программирования, что вы должны сделать ptr NULL после удаления, например

int* p=new int();
...
if (p) {
delete p;
p = (int *) NULL;
}
// double deletion is prevented, and ptr us not dangling any more
if (p) {
delete p;
p = (int *) NULL;
}

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

0
По вопросам рекламы [email protected]