it-roy-ru.com

Выделите память и сохраните строку в c

Мне было интересно, почему следующий код не работает

int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     test = "testingonly";
     free(test);
}

Подумав об этом, я предположил, что сначала я выделяю пространство для 12 символов в памяти, но при присваивании в следующей строке создается массив символов в стеке, а адрес памяти передается для проверки. Таким образом, free () пытается освободить место в стеке, что недопустимо. Это верно?

Итак, что будет правильным подходом для сохранения строки в куче? Является ли следующий общий путь?

int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     strcpy(test, "testingonly");
     free(test);
}
20
pluckyDuck
char *test = (char*) malloc(12*sizeof(char));

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|x|x|x|x|x|x|x|x|x|x|x|x|   (uninitialized memory, heap)
        +-+-+-+-+-+-+-+-+-+-+-+-+

test = "testingonly";

        +-+-+-+-+-+-+-+-+-+-+-+-+
test +  |x|x|x|x|x|x|x|x|x|x|x|x|
     |  +-+-+-+-+-+-+-+-+-+-+-+-+
     |  +-+-+-+-+-+-+-+-+-+-+-+-+
     +->|t|e|s|t|i|n|g|o|n|l|y|0|  
        +-+-+-+-+-+-+-+-+-+-+-+-+

free(test); // error, because test is no longer pointing to allocated space.

Вместо изменения указателя test необходимо скопировать строку "testingonly" в выделенное место, например, с помощью strcpy или используйте strdup. Обратите внимание, что такие функции, как malloc и strdup, возвращают NULL, если недостаточно памяти, и, следовательно, должны быть проверены.

char *test = (char*) malloc(12*sizeof(char));
strcpy(test, "testingonly");

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|t|e|s|t|i|n|g|o|n|l|y|0|
        +-+-+-+-+-+-+-+-+-+-+-+-+

или же

char *test = strdup("testingonly");

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|t|e|s|t|i|n|g|o|n|l|y|0|
        +-+-+-+-+-+-+-+-+-+-+-+-+
61
Anders

Вы уже ответили на свой вопрос. По сути, strcpy является подходящим способом копирования строки.

8
dicaprio

Первая версия не создает строку в стеке, но вы правы, что вам не разрешено free после назначения. Строковые литералы обычно хранятся в постоянных/доступных только для чтения разделах памяти. Назначение ничего не копирует, просто заставляет test указывать на эту область памяти. Вы не можете освободить это. Вы также не можете изменить эту строку.

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

5
Mat

Ну вы правы Теперь давайте рассмотрим первый кусок кода.

char *test = (char*) malloc(12*sizeof(char));

Над кодом нет проблем.

test = "testingonly";

Здесь вы изменили указатель test, что привело к утечке памяти. И когда вы пытаетесь освободить, вы освобождаете не фактический выделенный указатель, а один «только для тестирования» литерал, указывающий на. Литерал указывает на постоянную память, которая не может быть переопределена в обычных сценариях.

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

На ваш второй пункт да strcpy это обычный способ. Другие способы - это memcpy, если вы копируете необработанные байты.

ПРИМЕЧАНИЕ. Литералы не хранятся в стеке. Но вы не можете изменить место, где хранятся литералы.

4
havexz

код

#include <stdio.h>
int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     strcpy(test, "testingonly");
     printf("string is: %s\n",test);
     free(test);
     return 0;
}

буду работать 

0
Anes

Это для выделения памяти:

char *string;
string = (char *) malloc(15);

Это для сохранения данных:

strcpy(str, "kavitajain");
printf("String = %s,  Address = %u\n", str, str);
0
Kavita Jain