Как Вы знаете сколько пространства выделять с malloc ()?

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

существует большая хорошая эвристика для некоторых Полных NP проблем, но они - только образованное предположение в лучшем случае

10
задан Kredns 8 August 2009 в 04:22
поделиться

6 ответов

В этом фрагменте кода выделяется достаточно места для двухсимвольного имени.

Обычно строковый буфер заполняется откуда-то, например, при вводе-выводе. Если размер строки неизвестен заранее (например, чтение из файла или с клавиатуры), обычно используется один из трех подходов:

  • Определите максимальный размер для любой данной строки, выделите этот размер + 1 (для нулевой терминатор), прочитать не более этого количества символов и выполнить ошибку или слепо усечь, если было предоставлено слишком много символов. Не очень удобно для пользователя.

  • Перераспределяйте поэтапно (желательно, используя геометрические ряды, например, удвоение, чтобы избежать квадратичного поведения), и продолжайте читать, пока не будет достигнут конец. Нелегко кодировать.

  • Выделите фиксированный размер и надейтесь, что он не будет превышен, и ужасно выйдет из строя (или станет владельцем), когда это предположение не сработает. Легко кодировать, легко взламывать. Например, см. получает в стандартной библиотеке C. ( Никогда не используйте эту функцию. )

17
ответ дан 3 December 2019 в 15:35
поделиться

Для начала, sizeof (char) всегда равно 1, поэтому вы можете просто malloc (3) .

То, что вы выделяете, достаточно места для трех символов. Но имейте в виду, что вам понадобится один для нулевого терминатора для строк C.

Вы обычно найдете такие вещи, как:

#define NAME_SZ 30
: : :
char *name = malloc (NAME_SZ+1);

, чтобы получить достаточно памяти для имени и символа терминатора (помня, что строка "xyzzy" хранится в памяти как:

+---+---+---+---+---+----+
| x | y | z | z | y | \0 |
+---+---+---+---+---+----+

Иногда с массивами, не основанными на символах, вы увидите:

int *intArray = malloc (sizeof (int) * 22);

, который будет выделять достаточно места для 22 целых чисел.

5
ответ дан 3 December 2019 в 15:35
поделиться

Ваш вызов malloc выделит 3 байта памяти. sizeof (char) составляет 1 байт, а 2 байта указаны явно. Это дает вам достаточно места для строки размером 2 (вместе с символом завершения)

sizeof (char) составляет 1 байт, а 2 байта указаны явно. Это дает вам достаточно места для строки размером 2 (вместе с символом завершения)

sizeof (char) составляет 1 байт, а 2 байта указаны явно. Это дает вам достаточно места для строки размером 2 (вместе с символом завершения)

1
ответ дан 3 December 2019 в 15:35
поделиться

Это выделит три байта; 1 для sizeof (char) плюс два. Просто видя эту строку вне контекста, я не могу понять, почему она будет выделена таким образом или правильно ли (мне это кажется подозрительным).

Вам нужно выделить достаточно памяти для хранения всего, что вам нужно для размещения в этом. Например, если вы выделяете память для хранения строки, вам необходимо выделить достаточно памяти для хранения самой длинной ожидаемой строки плюс один байт для завершающего нуля. Если вы имеете дело со строками ASCII, это просто: один байт на символ плюс один. Если вы используете строки Unicode, все становится сложнее.

1
ответ дан 3 December 2019 в 15:35
поделиться

malloc () выделит блок памяти и вернет указатель на эту память в случае успеха и NULL в случае неудачи. размер блока памяти задается аргументом malloc в байтах.

оператор sizeof дает размер своего аргумента в байтах. Вторая строка пытается скопировать 20 символов (19 + NULL) в это пространство памяти. Это переполняет буфер и может вызвать что-то невероятно остроумное, например, перезапись соседней памяти или вызов segfault.

Третья строка может работать, например, если была выделена память прямо рядом с someString и «Привет, мир!» попал в это пространство памяти, он может напечатать вашу строку плюс все, что было в следующей области памяти. Если бы это второе пространство было завершено NULL, оно затем остановилось бы - если это не так, и в этом случае он отключился бы и в конечном итоге segfault.

Этот пример - довольно простая операция, но так легко ошибиться. C коварен - будьте осторожны.

3
ответ дан 3 December 2019 в 15:35
поделиться

Первое замечание - это хорошая привычка никогда не указывать абсолютные числа в аргументе malloc, всегда использовать sizeof и кратное. Как сказано выше, память, выделяемая для некоторых типов, зависит от компилятора и платформы. Чтобы гарантировать получение достаточно места для массива типа blob, лучше всего использовать что-то вроде этого:

blob *p_data = malloc(sizeof(blob) * length_of_array);

Таким образом, независимо от типа, как бы он ни просматривался в памяти, вы получите именно то, что вам нужно.

Во-вторых, ошибки сегментации и т. Д. C, как язык низкого уровня, не имеет проверки границ. Это означает, что проверять нечего: вы смотрите на индекс, которого нет в массиве. Фактически, это не мешает вам получать доступ к памяти где угодно, даже если она не принадлежит вашей программе (хотя ваша операционная система могла бы, вот что такое segfault). Вот почему всякий раз, когда вы передаете массив в C, вам также необходимо передать его длину, чтобы функция, получающая массив, знала, насколько он велик. Не забывайте, что «массив» на самом деле просто указатель на первый элемент. Это очень бесполезно при передаче строк - каждый строковый аргумент станет двумя аргументами, поэтому используется чит. Любая стандартная строка C завершается NULL. Последним символом в строке должно быть значение ASCII 0. Любые строковые функции работают с массивом, пока не увидят это, а затем остановятся. Таким образом, они не переполняют массив, но если его нет по какой-либо причине, они будут. Подразумевается

strlen("Hello")

, что это 5, но для его сохранения вам понадобится еще один символ. Например:

const char str1 = "Hello";
char *str2 = malloc(sizeof(char) * (strlen(str1) + 1));
strcpy(str2, str1);

И да, sizeof (char) не нужен, потому что он определен как 1, но я считаю его более ясным, и это определенно хорошая привычка.

1
ответ дан 3 December 2019 в 15:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: