Насколько безопасны и надежны строковые литералы C ++? - PullRequest
7 голосов
/ 30 апреля 2010

Итак, я хочу лучше понять, как работают строковые литералы в C ++. В основном меня интересуют ситуации, когда вы назначаете адрес строкового литерала указателю и передаете его. Например:

char* advice = "Don't stick your hands in the toaster.";

Теперь допустим, что я просто передаю эту строку, копируя указатели на время работы программы. Конечно, это, вероятно, не очень хорошая идея, но мне интересно, что на самом деле происходит за кулисами.

Для другого примера, скажем, мы создаем функцию, которая возвращает строковый литерал:

char* foo()
{
    // function does does stuff
    return "Yikes!"; // somebody's feeble attempt at an error message
}

Теперь допустим, что эта функция вызывается очень часто, а строковый литерал используется только примерно в половине случаев:

// situation #1: it's just randomly called without heed to the return value
foo(); 

// situation #2: the returned string is kept and used for who knows how long
char* retVal = foo();

В первой ситуации, что на самом деле происходит? Строка только что создана, но не используется и никогда не освобождается?

Во второй ситуации, будет ли эта строка сохраняться до тех пор, пока пользователь сочтет это необходимым? Что происходит, когда в этом больше нет необходимости ... будет ли тогда освобождена эта память (при условии, что ничто больше не указывает на это пространство)?

Не поймите меня неправильно, я не планирую использовать строковые литералы, подобные этой. Я планирую использовать контейнер для проверки моих строк (возможно, std :: string). В основном я просто хочу знать, могут ли эти ситуации вызвать проблемы с управлением памятью или повреждением данных.

Ответы [ 2 ]

22 голосов
/ 30 апреля 2010

Строковые литералы имеют тип const char[N] (где N - длина + 1) и размещаются статически. Вам не нужно беспокоиться о проблемах с памятью; если в вашей программе используется строка, она обрабатывается для вас и находится где-то в памяти программы (обычно только для чтения).

То есть это "одно и то же":

static const char str[] = "a string";
"a string"

Когда вы указываете на строковый литерал, вы указываете на первый символ в массиве. Фактически, поскольку типом является const char[], на него безопасно указывать только через const char*. Преобразование из строкового литерала в char* устарело и небезопасно.

// the "same"
static const char str[] = "a string";
const char* strPtr = str; // decays

const char* s1 = "a string";
char* s2 = "a string"; // allowed, implicit const_cast

*s1 = 'A'; // not allowed, it's const
*s2 = 'B'; // allowed, it's not const (but leads to undefined behavior)
1 голос
/ 30 апреля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...