2011-01-29 1 views
23

Я знаю, что это не так:Возвращает указатель на литеральный (или постоянный) массив символов (строка)?

char* getSomething() { 
    char szLocal[5]; 
    /* put something in the char array somehow */ 
    return szLocal; 
} 

... потому что szLocal может быть уничтожен через некоторое время после завершения функции.

Но это нормально?

char* getSomethingElse() { 
    return "something else"; 
} 
+3

См. [C Строковые литералы: куда они идут?] (Http://stackoverflow.com/questions/2589949/c-string-literals-where-do-they-go). –

+6

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

ответ

22

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

См. Также ответы на вопросы when does c/c++ allocate string literals.

+0

Я согласен с romkyns. Однако мы не знаем, в какой системе вы работаете? Там могут быть некоторые, которые не работают так. Для вашего собственного спокойствия вы можете попытаться целенаправленно прошивать память, где мы предлагаем, чтобы строка НЕ ​​жила. т. е. стек. Получите материал в стеке, объявив и усвоив некоторые локальные переменные, или вызовите некоторые другие функции с несколькими параметрами. В идеале вызовите другую функцию с несколькими параметрами, которые сами объявляют и назначают некоторые локальные переменные. – Dave

+0

OMG это место потрясающе.10 полезных ответов за 10 минут. Спасибо всем. (Я нахожусь на окнах x64, используя vs2010.) –

+6

Строковые литералы гарантированно живут на протяжении всего приложения. Это может быть не в постоянной памяти/неизменяемой памяти, но они гарантированно существуют для срока службы приложения, поэтому возврат указателя на один в порядке. – nos

6

Это нормально с точки зрения распределения: строковый литерал неявно static. Неверно возвращать указатель не const в литерал.

Если вы хотите вернуть измененную (не const) строку, объявите ее static char[]. Или лучше, вернуть копию:

return strdup("something else"); 

Не забудьте free потом. strdup не является ISO, но доступен почти везде (за исключением MSVC, я считаю).

+0

strdup недоступен на msvc? ты уверен ? – Mandrake

+0

@Arabcoder: нет, я не уверен, и, пожалуйста, поправьте меня, если я ошибаюсь. Я не делаю MSVC. –

+1

Хороший вопрос о const. Не мог бы (хороший) компилятор это поймать - попытка лишить const char для не-const char? –

4

Тип строкового литерала является const char * (см комментарии ниже) static char[], но неизменны. Строковый литерал представляет указатель на статически выделенную память. Поэтому:

  1. Прекрасно, чтобы вернуть такой указатель.

  2. Ваша функция возвращает тип обязательно должны быть совместимы с const char*, то есть, тип возвращаемого char * даст вам, по крайней мере предупреждение может дать вам неприятности позже.

  3. Если вы можете возвращать строку или литерал или строку malloc, вы должны быть очень осторожны в управлении памятью. free Ввод строкового литерала, вероятно, будет segfault.

+2

На самом деле тип 'static const char []', то есть ближе к 'const char * const'. Вы не можете увеличивать или уменьшать литерал. –

+2

@larsman: Нет, к сожалению, по историческим причинам его тип не является 'const' квалифицированным. Но вы не имеете права изменить его: ((Поэтому, конечно, неплохо объявить возвращаемое значение 'const', но язык не применяет это. –

+0

@Jens: Вы правы, это' статические char [] '. –

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