2010-10-13 3 views
3

сегмент кода приведен ниже компилирует и при запуске дает результат в виде:Странная указатель проблема

$ make 
gcc -g -Wall -o test test.c 
$ ./test 
string 

/* code1 */

#include<stdio.h> 
char *somefunc1() 
{ 
    char *temp="string"; 
    return temp; 
} 
int main(int argc,char *argv[]) 
{ 
    puts(somefunc1()); 
    return 0; 
} 

тогда небольшой модификации этого кода дает различные результаты:

$ make 
gcc -g -Wall -o test test.c 
test.c: In function ‘somefunc1’: 
test.c:5: warning: function returns address of local variable 
$ ./test 

/* code 2 */ 

#include<stdio.h> 
char *somefunc1() 
{ 
    char temp[] ="string"; 
    return temp; 
} 
int main(int argc,char *argv[]) 
{ 
    puts(somefunc1()); 
    return 0; 
} 

Почему это происходит?

+2

Конечно, вы могли бы получить лучший заголовок, чем «проблема странного указателя». – Eyal

ответ

4

char *temp = "string"; создаст указатель temp, который указывает на строку litteral. Этот строковый литерал хранится в сегменте данных исполняемого кода. Он неизменен, и адрес остается действительным после возвращения функции.

char temp[] = "string"; выделит 7 символов в стеке и установит их равными «string». Это изменчивые символы. В вашем примере возвращаемое значение указывает на символы, которые больше недействительны при возврате функции.

+0

s/уничтожено/больше не действует /? –

+0

они действительно разрушены, как странно, я не ожидал этого: D (p.s., я бы никогда не использовал char []). –

+0

@ Hassan Syed: как вы заявили, вы можете объявить 'temp' static, чтобы сохранить его после вызова функции, но это не ужасно отличный дизайн. – JoshD

-1

когда вы делаете char * temp = "string"; память для temp выделяется в куче и остается там до выполнения программы. тогда как когда вы делаете char temp [] = "string"; память выделяется в стеке, которая удаляется или недействительна после того, как вы вышли из области действия. В вашей программе во втором случае, когда вы находитесь вне функции something1, возвращаемый указатель становится недействительным. В первом случае, поскольку массив находится в куче, память не является недействительной. Но тогда вы успешно просочились в память.

+0

Хороший вопрос об утечке памяти. –

+2

char * temp = "string" не выделяется в куче. – JoshD

+1

-1. Здесь нет кучи. Распределение кучи происходит только тогда, когда вызывается одна из функций 'malloc',' calloc' или 'realloc'. Таким образом, в первой программе нет утечки памяти. –

4

В первом примере вы возвращаете адрес строкового литерала. Этот литерал существует до тех пор, пока программа выполняется, чтобы код был безопасным.

Во втором примере вы создаете (функциональный локальный) массив, который инициализируется, чтобы содержать строку string. Затем вы возвращаетесь к адресу (первого элемента) этого массива, но массив уничтожается, как только вы покидаете функцию. Об этом предупреждает ваш компилятор. Использование указателя, возвращенного с somefunc1, приводит к неопределенным поведением, поскольку оно больше не относится к существующему объекту.

+0

Очень хорошее объяснение (и первое правильное) +1. – JoshD

1

Переменные стека теряются после выхода из функции и, следовательно, «странное поведение» во втором случае.

Смежные вопросы