Если ссылка на константные символьные строки указателями, постоянно ли занята память? - PullRequest
1 голос
/ 23 сентября 2011

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

char *giveString (void)
{
    char string[] = "Test";
    return string;
}
int main (void)
{
    char *string = giveString ();
    printf ("%s\n", string);
}

Запуск дает различные результаты, он просто печатает дрянь.Из этого я понял, что массив char с именем string в giveString () хранится в кадре стека функции giveString () во время его работы.Но если я изменил тип строки в giveString () с массива char на указатель char:

char *string = "Test";

я не получу предупреждений, и программа выведет «Test».Значит ли это, что строка символов «Test» теперь находится в куче?Похоже, он больше не находится в фрейме стека метода giveString ().Что именно происходит в каждом из этих двух случаев?И если эта символьная строка находится в куче, так что все части программы могут получить к ней доступ через указатель, не будет ли она освобождена до завершения программы?Или освободилось бы пространство памяти, если бы на него не было указателей, как если бы я не вернул указатель на main?(Но это возможно только с сборщиком мусора, как в Java, верно?) Является ли это особым случаем выделения кучи, который применим только к указателям на строки константных символов (жестко закодированные строки)?

Ответы [ 3 ]

6 голосов
/ 23 сентября 2011

Вы, кажется, не понимаете, что делают следующие утверждения.

char string[] = "Test";

Этот код означает: создать массив в фрейме локального стека достаточного размера и скопировать в него содержимое постоянной строки «Test».

char *string = "Test";

Этот код означает: установить указатель, указывающий на постоянную строку «Тест».

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

Вы можете думать о фактической строке «Test» как о глобальной и всегда присутствующей в памяти, но концепция выделения и освобождения обычно не применима к константным данным.

0 голосов
/ 23 сентября 2011

Это потому, что во втором случае вы создаете постоянную строку:

char *string = "Test";

Значение, указанное строкой, является константой и никогда не может измениться, поэтому оно выделяется во время компиляции как статическая переменная (ноэто все еще стек, а не куча).

0 голосов
/ 23 сентября 2011

Нет. Строка "Test" все еще находится в стеке, она находится только в части data стека, которая в основном настраивается до запуска программы. Он есть, но вы можете думать о нем как о «глобальных» данных.

Следующее может прояснить это для вас немного:

char string[] = "Test"; // declare a local array, and copy "Test" into it
char* string = "Test";  // declare a local pointer and point it at the "Test"
                        // string in the data section of the stack
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...