Я понимаю, как работает malloc (). Мой вопрос, я увижу такие вещи:
#define A_MEGABYTE (1024 * 1024)
char *some_memory;
size_t size_to_allocate = A_MEGABYTE;
some_memory = (char *)malloc(size_to_allocate);
sprintf(some_memory, "Hello World");
printf("%s\n", some_memory);
free(some_memory);
Я опустил проверку ошибок для краткости. Мой вопрос: не могли бы вы просто сделать это, инициализировав указатель на какое-то статическое хранилище в памяти? возможно:
char *some_memory = "Hello World";
В какой момент вам действительно нужно выделить память самостоятельно вместо объявления / инициализации значений, которые вам нужно сохранить?
c
memory
memory-management
рандомбиты
источник
источник
malloc()
может потерпеть неудачу!Ответы:
char *some_memory = "Hello World";
создает указатель на строковую константу. Это означает, что строка «Hello World» будет где-то в доступной только для чтения части памяти, и у вас есть только указатель на нее. Вы можете использовать строку только для чтения. Вы не можете вносить в него изменения. Пример:
some_memory[0] = 'h';
Просит неприятностей.
С другой стороны
some_memory = (char *)malloc(size_to_allocate);
выделяет массив char (переменную), а some_memory указывает на эту выделенную память. Теперь этот массив доступен для чтения и записи. Теперь вы можете:
some_memory[0] = 'h';
и содержимое массива изменится на "hello World"
источник
const char *s = "hi";
Разве это не требуется стандартом?const char const* s;
Для этого точного примера malloc мало пригоден.
Основная причина, по которой требуется malloc, - это когда у вас есть данные, время жизни которых должно отличаться от области кода. Ваш код вызывает malloc в одной подпрограмме, где-то хранит указатель и, в конечном итоге, вызывает free в другой подпрограмме.
Вторая причина заключается в том, что C не имеет возможности узнать, достаточно ли места в стеке осталось для выделения. Если ваш код должен быть на 100% устойчивым, безопаснее использовать malloc, потому что тогда ваш код может знать, что выделение не выполнено, и обрабатывать его.
источник
malloc - прекрасный инструмент для выделения, перераспределения и освобождения памяти во время выполнения, по сравнению со статическими объявлениями, такими как пример вашего hello world, которые обрабатываются во время компиляции и, следовательно, не могут быть изменены в размере.
Поэтому Malloc всегда полезен, когда вы имеете дело с данными произвольного размера, например, при чтении содержимого файла или работе с сокетами, и вы не знаете, какой размер обрабатываемых данных требуется.
Конечно, в тривиальном примере, подобном приведенному вами, malloc не является волшебным «правильным инструментом для правильной работы», но для более сложных случаев (например, создание массива произвольного размера во время выполнения) это единственный способ идти.
источник
Если вы не знаете точный размер памяти, которую нужно использовать, вам понадобится динамическое выделение (
malloc
). Примером может быть ситуация, когда пользователь открывает файл в вашем приложении. Вам нужно будет прочитать содержимое файла в памяти, но, конечно, вы не знаете размер файла заранее, поскольку пользователь выбирает файл на месте, во время выполнения. Так что в основном вам нужно,malloc
когда вы заранее не знаете размер данных, с которыми работаете. По крайней мере, это одна из основных причин использованияmalloc
. В вашем примере с простой строкой, размер которой вы уже знаете во время компиляции (плюс вы не хотите ее изменять), нет смысла динамически выделять ее.Немного не по теме, но ... вы должны быть очень осторожны, чтобы не создавать утечек памяти при использовании
malloc
. Рассмотрим этот код:int do_something() { uint8_t* someMemory = (uint8_t*)malloc(1024); // Do some stuff if ( /* some error occured */ ) return -1; // Do some other stuff free(someMemory); return result; }
Вы видите, что не так с этим кодом? Там это условный оператор возврата между
malloc
иfree
. Сначала это может показаться нормальным, но подумайте об этом. Если произойдет ошибка, вы вернетесь, не освобождая выделенную память. Это частый источник утечек памяти.Конечно, это очень простой пример, и здесь очень легко увидеть ошибку, но представьте себе сотни строк кода, усеянных указателями,
malloc
s,free
s и всеми видами обработки ошибок. Все может очень быстро запутаться. Это одна из причин, по которой я предпочитаю современный C ++ в соответствующих случаях, но это уже совсем другая тема.Поэтому всякий раз, когда вы используете
malloc
, всегда убедитесь, что ваша память как можноfree
хуже.источник
char *some_memory = "Hello World"; sprintf(some_memory, "Goodbye...");
является незаконным, строковые литералы -
const
.Это выделит 12-байтовый массив символов в стеке или глобально (в зависимости от того, где он объявлен).
char some_memory[] = "Hello World";
Если вы хотите оставить место для дальнейших манипуляций, вы можете указать, что размер массива должен быть больше. (Однако, пожалуйста, не кладите 1 МБ в стек.)
#define LINE_LEN 80 char some_memory[LINE_LEN] = "Hello World"; strcpy(some_memory, "Goodbye, sad world..."); printf("%s\n", some_memory);
источник
Одна из причин, по которой необходимо выделить память, заключается в том, что вы хотите изменить ее во время выполнения. В этом случае можно использовать malloc или буфер в стеке. Простой пример присвоения указателю «Hello World» определяет память, которая «обычно» не может быть изменена во время выполнения.
источник