указатель на локальную переменную

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

versus
Сообщения: 45
Зарегистрирован: 12 май 2004, 01:37

привет
подскажи плз, что то я запутался

вот на такой код, gcc, естественного говорит ворнинг про использоване адреса локальной переменной

Код: Выделить всё

#include <stdio.h>
#include <unistd.h>

char* some_function()
{
    char str[1024] = "hello world!";

    return str;
}

int main()
{
    char* ptr;
    ptr = some_function();

// usleep((long)1E3) /* подождать пока локальная переменная удалится 

    printf("%s\n", ptr);

    return 0;
}
понятно, что код этот совсем некорректен, в том смысле что лучше было бы использовать malloc и free, но все таки не смотря на ворнинг к большому для меня удивлению программа все таки печатает "hello world!".. как это понимать? разве память занимаемая str не должна удалится после завершения some_function? и тогда при попытке printf получится segfault... однако вместо этого нормальный вывод. Почему?
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Этот код работает случайно, потому что компилятору нет резона занулять локальные переменные, и они там остаются по старым адресам.
Но программист должен думать, что там уже ничего нет.
2B OR NOT(2B) = FF
Hup
Сообщения: 207
Зарегистрирован: 05 мар 2004, 05:31
Откуда: Владивосток
Контактная информация:

Я так полагаю. что строка просто висит в памяти... Нужно посмотреть Турбо дебагером дамб памяти
Усложнять - легко, упрощать - сложно
versus
Сообщения: 45
Зарегистрирован: 12 май 2004, 01:37

Absurd, спасибо.
Kolinus
Сообщения: 449
Зарегистрирован: 23 авг 2004, 14:02
Откуда: Минск

Absurd прав. Как говорят мои преподаватели - это типичная ошибка второкурсника.
Если после вызова some_function обЪявить еще какую-нить переменную и проинициализировать ее то ptr скорее всего "свалится" с нужной тебе строки
В SAD - все в SAD.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

В принципе, если есть большая нужда возвращать строчку типа const char * или char * (хуже), то можно массив str[] объявить как
статический

Код: Выделить всё

const char* some_function()
{
    static char str[1024] = "hello world!";
    return str;
}
В таком случае строка str будет жить не в стеке, а в области данных, где ее никто не будет трогать.
2B OR NOT(2B) = FF
Kolinus
Сообщения: 449
Зарегистрирован: 23 авг 2004, 14:02
Откуда: Минск

Еще есть способ - после того как сделал вызов такого метода, сразу вызывать strcpy в локальную переменную функции main - но это опять же если только сильно надо ;)
В SAD - все в SAD.
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

Удивительно но факт, следующий код так же будет полностью корректным -

Код: Выделить всё

const char* some_function() 
{ 
    char* str = "hello world!"; 
    return str; 
} 
в этом случае строчка "hello world!" становится статической константой и существует даже до вызова функции не говоря уж о возвращении из неё. В отличии от char str[1024] = "hello world!" когда создается локальный массив с который копируется эта статическая строчка
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

Hawk, неудивительно: по-сути ты просто возвращаешь адрес на константную строку (литерал), неважно, что объявленный локально - он все равно фиксирован в памяти
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

Eugie и я о том же
Ответить