Могу ли я сохранить (и использовать) символ *, переданный в функцию после его завершения? - PullRequest
3 голосов
/ 04 мая 2019

Я пытаюсь передать литерал в функцию, присвоить его структуре и использовать позже.Нужно ли мне malloc() и strcpy(), или я могу сохранить char* для последующего использования (статически выделяется или нет)?

Пример минималистического кода ниже:

struct data {
    char *string;
    ...;
}
struct data *create_data(char *input_string, ...) {
    struct data *result = malloc(sizeof(struct data));
    result->string = input_string;
    return result;
}

struct data *string = create_data("Hey", ...);
printf("%s", data->string);

или

struct data *create_data(char *input_string, ...) {
    struct data *result = malloc(sizeof(struct data));
    result->string = malloc(sizeof(input_string));
    strcpy(result->string, input_string);
    return result;
}

struct data *string = create_data("Hey",...);
printf("%s", data->string);

Могу ли я ожидать, что сработает первый, чтобы данные в памяти не перезаписывались или это небезопасно предположить?

1 Ответ

7 голосов
/ 04 мая 2019

Строковые литералы имеют статическая продолжительность хранения .Для такого объекта C11 6.2.4p3 говорит, что:

Его время жизни - это полное выполнение программы, и его сохраненное значение инициализируется только один раз, до запуска программы.

И жизни C11 6.2.4p2

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

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


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

И поскольку строковые литералы являются неизменяемыми, вы должны скопировать их, если хотите изменить строку.


Наконец, malloc(sizeof(input_string)) не так, это должно быть malloc(strlen(input_string) + 1).Для дублирования строки POSIX имеет функцию strdup .

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