2013-06-23 4 views
-2

Пожалуйста, рассмотрите следующий фрагмент кода C++. Я передаю ссылку на char * в качестве параметра функции.C++ Память стека не освобождается

void name(char **str){ 
    *str=(char *)"JUSTFORFUN"; 
} 


int main(int argc, const char * argv[]) 
{ 
    char *test; 
    name(&test); 
    cout<<test; //Prints "JUSTFORFUN" 
    //delete(test); //Throws error "pointer being freed was not allocated" 
    return 0; 
} 

Я думаю, что память, выделенная для хранения «JustForFun» в имени функции() выделяется в стеке. Поэтому, когда элемент управления выходит из имени(), память, связанная с (char *) "JUSTFORFUN", должна быть освобождена компилятором. Мой вопрос: почему я все еще получаю правильный вывод, когда я печатаю тест? Должна ли она печатать нежелательную ценность?

Когда я делаю что-то подобное для int. Я получаю ожидаемый результат.

void nameint(int **value){ 
    int val=5; 
    *value=&val; 
} 

int main(int argc, const char * argv[]) 
{ 
    int *val; 
    nameint(&val); 
    cout<<*val; //Prints a junk value 1073828160  
    return 0; 
} 

Почему существует разница между поведением int и char *?

+1

«Я думаю, что память, выделенная для хранения« JUSTFORFUN »в имени функции(), выделяется в стеке». - это не. – Mat

+0

@Mat - см. Http://stackoverflow.com/questions/51592/is-there-a-need-to-destroy-char-string-or-char-new-char6 – Mishra

+1

Это не говорит нигде, что строка помещается в стек. Это не так, это глобальный (возможно, хранящийся в разделе только для чтения). – Mat

ответ

1

Строковый литерал "JUSTFORFUN" is не хранится в стеке - он имеет статическую продолжительность хранения. Несмотря на то, что внутри функции присутствует только , строковый литерал не является локальным для этой функции (нет строкового литерала - все они имеют статическую продолжительность хранения).

Таким образом, поведение первой программы действительно хорошо определено. После того, как name возвращает, val содержит адрес строкового литерала со статическим временем хранения, который вы затем печатаете.

В вашей второй программе вы возвращаете адрес int, который является локальным для этой функции. После возвращения функции int больше не существует, поэтому использование этого параметра дает неопределенное поведение - в типичном случае он, вероятно, распечатает любое значение, которое биты, находящиеся на этом адресе, будут работать, но нет никакой гарантии, что это будет делать.

1

"JUSTFORFUN" не выделяется в стеке. Он сохраняется вместе с остальными статическими данными вашей программы. Функция name хранит указатель на стеке. Этот указатель указывает на статические данные.

Ваш int, однако, : хранится в стеке. Функция nameint возвращает указатель на эту позицию в стеке. Выполнение чего-то подобного может привести к краху вашей программы довольно быстро.

0

два случая:

В струнном случае, вы не распределяющие любую памяти, так как сырые строки, как const char* x = "sdfsdf" сохраняются в секции .data исполняемого файла, так что вы можете думать об этом как статических неизменных данных который загружается программой (нет распределения распределения памяти вообще!)

Во втором случае val выделяется в стеке функций, а затем он становится недействительным, когда функция возвращается.

0

Я думаю, что память, выделенную для хранения «JustForFun» в имени функции() выделяется в стеке

Нет, это не так. Строковые литералы неявно имеют продолжительность хранения static. Их жизнь - это программа. Без delete ваша первая программа верна.

Выдает ошибку «указатель освобождения не было выделено»

Конечно, это делает, потому что вы не создали этот объект с помощью new.

Почему существует разница в поведении int и char *?

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