Почему вы указываете размер при использовании malloc в C? - PullRequest
21 голосов
/ 06 августа 2009

Возьмите следующий код:

int *p = malloc(2 * sizeof *p);

p[0] = 10;  //Using the two spaces I
p[1] = 20;  //allocated with malloc before.

p[2] = 30;  //Using another space that I didn't allocate for. 

printf("%d", *(p+1)); //Correctly prints 20
printf("%d", *(p+2)); //Also, correctly prints 30
                      //although I didn't allocate space for it

С помощью строки malloc(2 * sizeof *p) Я выделяю пространство для двух целых чисел, верно? Но если я добавлю int к третьей позиции, я все равно получу правильное распределение и извлечение.

Итак, мой вопрос, , почему вы указываете размер при использовании malloc?

Ответы [ 17 ]

1 голос
/ 07 августа 2009

Вы просите место для двух целых чисел. p [3] предполагает, что у вас есть место для 4 целых чисел!

===================

Вы должны указать malloc, сколько вам нужно, потому что он не может угадать сколько памяти вам нужно.

malloc может делать все, что захочет, при условии, что он возвращает как минимум объем памяти, который вы запрашиваете.

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

Как часть "контракта" на использование malloc, вы обязаны никогда не ссылаться на память сверх того, что вы просили, потому что вы гарантированно получите только запрошенную сумму.

0 голосов
/ 07 августа 2009

Причина, по которой размер, назначенный функции malloc (), заключается в том, что диспетчер памяти отслеживает, сколько места было выделено для каждого процесса в вашей системе. Эти таблицы помогают системе узнать, кто выделил, сколько места, и какие адреса свободны ().

Во-вторых, c позволяет писать в любую часть оперативной памяти в любое время. Ядра могут помешать вам писать в определенные разделы, вызывая сбои защиты, но ничто не мешает программисту пытаться.

В-третьих, по всей вероятности, malloc () в первый раз, вероятно, не просто выделяет 8 байтов вашему процессу. Это зависит от реализации, но более вероятно, что диспетчер памяти выделит полную страницу для вашего использования только потому, что легче выделить куски размера страницы .... тогда последующие malloc () разделят ранее malloc ( ) Ред.

0 голосов
/ 07 августа 2009

Как уже говорили, вы пишете в память, которая фактически не выделена, то есть что-то может произойти, чтобы перезаписать ваши данные. Чтобы продемонстрировать проблему, вы можете попробовать что-то вроде этого:

int *p = malloc(2 * sizeof(int));
p[0] = 10; p[1] = 20; p[2] = 30;
int *q = malloc(2 * sizeof(int));
q[0] = 0; // This may or may not get written to p[2], overwriting your 30.

printf("%d", p[0]); // Correctly prints 10
printf("%d", p[1]); // Correctly prints 20
printf("%d", p[2]); // May print 30, or 0, or possibly something else entirely.

Нет способа гарантировать, что ваша программа выделит место для q при p [2]. На самом деле он может выбрать совершенно другое место. Но для такой простой программы, как эта, это кажется вероятным, и если она действительно выделяет q в том месте, где будет p [2], то она явно продемонстрирует ошибку вне диапазона.

0 голосов
/ 06 августа 2009

Поскольку malloc () размещается в байтах. Итак, если вы хотите выделить (например) 2 целых числа, вы должны указать размер в байтах 2 целых числа. Размер целого числа можно найти с помощью sizeof (int), поэтому размер в байтах по 2 целых числа равен 2 * sizeof (int). Соберите все это вместе, и вы получите:

int * p = malloc(2 * sizeof(int));

Примечание: учитывая, что вышеизложенное выделяет место только для ДВУХ целых чисел, вы очень капризны в назначении третьего Тебе повезло, что он не разбился. :)

0 голосов
/ 07 августа 2009

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

0 голосов
/ 07 августа 2009

До:

int *p = malloc(2 * sizeof(*p)); // wrong (if type is something greater than a machine word)

[type] *p = malloc(2 * sizeof([type])); // right.
0 голосов
/ 06 августа 2009

Когда вы используете * (p + 3), вы обращаетесь за пределы даже при использовании 2 * sizeof (* p), следовательно, вы получаете доступ к недопустимому блоку памяти, идеально подходящему для ошибок сегмента.

В противном случае вы указываете размер b / c, функция не знает, какой объем блока из памяти кучи выделяется вашей программе для этого указателя.

...