Скажем, у меня есть фрагмент кода

char *str = malloc(sizeof(char)*10)
// some code to add content to the string in some way

Чтобы создать строку из 10 символов. Если я затем скопирую str с strcpy из стандартной строковой библиотеки в новую переменную, например,

char *copy;
strcpy(copy, str);

Я знаю, что мне нужно освободить str с помощью free(str), но достаточно ли этого? Или strcpy также динамически выделяет память для copy, если используется в строке, созданной из malloc?

0
SomeCoderOnTheWeb 26 Ноя 2021 в 12:58

3 ответа

Лучший ответ

Или strcpy также динамически выделяет память для копирования

Нет, strcpy ничего не знает о памяти, поэтому ваш код копирует строку в неинициализированный указатель, указывающий на la-la land.

Если вы хотите выделить + копирование в одном и том же вызове, для этого есть нестандартный strdup (который, похоже, будет добавлен к стандарту C в следующей версии языка).

Или просто сделайте char *copy = malloc(strlen(str)+1);, а затем strcpy. Помните, что всегда оставляйте место для нулевого терминатора.

2
Lundin 26 Ноя 2021 в 13:02
Afaik strcpy также копирует нулевой терминатор. Значит ли это, что если бы я был на 100% уверен, что строка, которую я копирую, имеет нулевой терминатор, мне не понадобится +1 в вашем вызове malloc?
 – 
SomeCoderOnTheWeb
26 Ноя 2021 в 13:18
strcpy копирует терминатор, но вы должны убедиться, что в нем есть место. Если длина строки 10 символов, вам, очевидно, нужно выделить 11, иначе strcpy будет обращаться к данным за пределами границ, когда записывает терминатор.
 – 
Lundin
26 Ноя 2021 в 13:22
Нет, поскольку strlen не учитывает нулевой ограничитель. strlen("abc" ) == 3, в то время как базовый массив char имеет размер 4, {'a','b','c', '\0'} и то, что необходимо скопировать (и копируется strcpy).
 – 
alagner
26 Ноя 2021 в 13:23

strcpy не выделяется, поэтому ваш второй фрагмент недействителен, если copy не инициализирован каким-либо буфером (независимо от того, выделен ли он стеком или кучей) или является достаточно большим массивом.

Боковое примечание: если вы не знаете точную длину исходной строки, вам необходимо убедиться, что размер целевого буфера не превышен (например, с помощью strncpy или предоставления достаточно большого целевого буфера).

Думаю, документация должна подробно ответить на ваш вопрос.

1
alagner 26 Ноя 2021 в 13:07
1
strncpy - плохой выбор, так как он может оставить вас без нулевого терминатора.
 – 
Jabberwocky
26 Ноя 2021 в 13:09
Может, но с известным размером, ИМХО, это не такая уж большая проблема. Конечно, я бы, наверное, тоже выбрал что-нибудь еще, но это действительно зависит от контекста.
 – 
alagner
26 Ноя 2021 в 13:13
Что бы вы посоветовали тогда?
 – 
SomeCoderOnTheWeb
26 Ноя 2021 в 13:14
Используйте strcpy и убедитесь, что целевой буфер достаточно длинный.
 – 
Jabberwocky
26 Ноя 2021 в 13:16
1
Сказать людям использовать strncpy - всегда плохой и неверный совет. Изучите Опасно ли strcpy и что следует использовать вместо этого?
 – 
Lundin
26 Ноя 2021 в 13:25

Для начала копия указателя не инициализируется

char *copy;

Итак, этот призыв strcoy

strcpy(copy, str);

Приводит к неопределенному поведению.

Указатель copy должен указывать на массив символов, куда будет скопирована строка, на которую указывает указатель str.

Вам нужно освободить то, что было выделено с помощью malloc, calloc или realloc.

Итак, если целевой массив, на который указывает копия указателя, был динамически выделен, например,

char *copy = malloc( 10 * sizeof( char ) );

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

Это не имеет ничего общего с функцией strcpy, которая просто копирует строку из одного массива символов в другой массив символов.

0
Vlad from Moscow 26 Ноя 2021 в 13:27