Подтвердить что ты не робот

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

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

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

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

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

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

Ответ 1

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|
        +-+-+-+-+-+-+-+-+-+-+-+-+

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

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

Выше кода нет проблем.

test = "testingonly";

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

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

К вашему второму пункту да strcpy - обычный способ. Другими способами являются "memcpy", если вы копируете необработанные байты.

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

Ответ 5

код

#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;
}

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

Ответ 6

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

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

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

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