Срок действия указателя после разматывания стека
В C++ указатель остается действительным после разматывания стека или нет?
5 ответов
Это зависит от того, на что указывает ваш указатель. Если он указывает на кучу памяти, он все еще остается в силе. Если он указывает на стековую память, он становится недействительным.
Это зависит от хранения указанного объекта. Если этот объект был размещен в стеке, то указатель обязательно станет недействительным - разматывание стека будет правильно уничтожать объект. Если объект был выделен в куче, указатель становится недействительным только при наличии некоторой переменной RAII, которая освобождает объект во время разматывания стека.
Рассмотрим несколько примеров:
void* f1a()
{
void* p = malloc(10);
return p;
}
...такой же как...
void* f1b()
{
return malloc(10);
}
Это нормально, так как указатели находятся в куче и, следовательно, не зависят от стека, вызовов функций и программных областей. Значение указателя копируется при возврате функции.
int* f2()
{
int x;
return &x; // pointer to x - about to become invalid!
}
Выше возвращает указатель на переменную x
в стеке, который будет исправлен (x
потерял), когда функция возвращается.
Нет. С помощью стека Разматывание всех переменных / указателей, которые объявлены в областях неупорядоченной части стека, уничтожается.
Кроме того, правило принимает во внимание Storage Type
переменных.
например: A static
переменная сохраняет свое значение между вызовами функций, что означает, что она не уничтожается при разматывании стека. Это связано с тем, что статические переменные хранятся не в стеке, а в BSS или сегментах данных.
Local variables
(Auto storage type
), созданный в стеке внутри функции, всегда будет уничтожен, когда функция вернется и размотка стека произойдет.
Указатели, выделенные с памятью в куче, не будут уничтожены при разматывании стека, поскольку они размещены в куче, а не в стеке.
Запомните одно важное правило: НИКОГДА не возвращайте указатели или ссылки на локальные переменные внутри функции. Указатель или ссылка будут содержать мусорные значения.
Просто констатировать одну дополнительную вещь, которую я считаю важной
скажем, у нас есть это заявление
obj* objptr = new obj(9) //allocate memory on heap and use constructor
если здесь происходит исключение.. кучи памяти возвращается обратно.... т.е. нет утечки памяти...
причина в том... не из-за разматывания стека... а из-за того, как новый оператор преобразуется в следующий сгенерированный код, оператор try catch реализован в новом операторе... что-то вроде этого...
void * operator new(size_t s)
{
try
{
void * ptr=new(malloc (s))sample(); //placement new
ptr->...
}
catch(..)
{
operator delete(ptr); //<= notice here so if an exception occur then first it is caught here which releases the memory
}
}
однако, если в пределах объекта сделано некоторое выделение памяти, которое все еще не освобождается..