Как действительно освобождает, знают, сколько освободить?

Любой объект ориентировал DAL, соединяющийся с любой системой хранения, которая не сохраняет реализации объектов ORM. ORM, как обычно понимают, означает, что чему-то нравится, в спящем режиме, но важной вещью является обработка несоответствий импеданса.

[Расширенный]

На уровне данных, импеданс несоответствия происходят при отображении данных одного типа (реляционного) в данные другого (OO).

, Например, как сколько раз Вы видели строку ниже в Вашем DAL?

db.AddInParameter(dbCommand, "Name", DbType.String, name);

Или другая сторона

customerId = Convert.ToInt64(dr["CustomerID"].ToString());

Много проблем подходят при отображении примитивных типов данных.

На уровне объектов, Ваш DAL должен возвращать структуры, которые Вы намереваетесь использовать. Будьте этим своего рода бизнес-объект или просто набор необработанных данных. И Ваш собственный DAL и ORM должны обработать это.

На уровне дизайна, объекты, которые Вы создаете, являются отражающими из Ваших хранивших данных. Таким образом, структурные различия могут произойти. Они также обрабатываются для Вас в решениях ORM, но Вы были бы вынуждены сделать то же в DAL. Например, в Вашем коде OO было бы хорошо реализовать надлежащее наследование, но это не делает тайный легко во что-то реляционное.

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

359
задан Prashant Kumar 27 November 2013 в 11:25
поделиться

8 ответов

Когда вы вызываете malloc () , вы указываете объем памяти для выделения. Фактически используемый объем памяти немного больше указанного и включает дополнительную информацию, которая фиксирует (по крайней мере) размер блока. Вы не можете (надежно) получить доступ к этой другой информации - и вы не должны: -).

Когда вы вызываете free () , он просто просматривает дополнительную информацию, чтобы узнать, насколько велик блок есть.

328
ответ дан 23 November 2019 в 00:19
поделиться

malloc () и free () зависят от системы / компилятора, поэтому сложно дать конкретный ответ.

Дополнительная информация по этому поводу другой вопрос .

3
ответ дан 23 November 2019 в 00:19
поделиться

Из списка часто задаваемых вопросов comp.lang.c : Как free узнает, сколько байтов нужно освободить?

Реализация malloc / free запоминает размер каждого блока по мере его размещения, поэтому нет необходимости напоминать ему размер при освобождении. (Как правило, размер хранится рядом с выделенным блоком, поэтому обычно что-то ломается, если границы выделенного блока даже немного превышаются)

47
ответ дан 23 November 2019 в 00:19
поделиться

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

Я сам никогда не реализовывал такой, но думаю, память верна перед выделенным блоком может содержать метаинформацию.

2
ответ дан 23 November 2019 в 00:19
поделиться

По теме Библиотека GLib имеет функции выделения памяти, которые не сохраняют неявный размер - а затем вы просто передаете параметр размера в значение free.

4
ответ дан 23 November 2019 в 00:19
поделиться

Чтобы ответить на вторую половину вашего вопроса: да, вы можете, и довольно распространенный шаблон в C следующий:

typedef struct {
    size_t numElements
    int elements[1]; /* but enough space malloced for numElements at runtime */
} IntArray_t;

#define SIZE 10
IntArray_t* myArray = malloc(sizeof(intArray_t) + SIZE * sizeof(int));
myArray->numElements = SIZE;
1
ответ дан 23 November 2019 в 00:19
поделиться

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


В случае malloc , распределитель кучи сохраняет отображение исходного возвращенного указателя с соответствующими деталями, необходимыми для бесплатно ing память позже. Обычно это включает в себя сохранение размера области памяти в любой форме, относящейся к используемому распределителю, например, необработанный размер или узел в двоичном дереве, используемый для отслеживания распределения, или количество используемых «единиц» памяти.

free не выдаст ошибку, если вы «переименуете» указатель или скопируете его каким-либо образом. Однако это количество ссылок не учитывается, и только первый свободный будет правильным. Дополнительные free s являются ошибками "double free".

Попытка освободить любой указатель со значением, отличным от возвращаемого предыдущими malloc s, и как все же необъявленное - это ошибка. Невозможно частично освободить области памяти, возвращенные из malloc .

или узел в двоичном дереве, используемый для отслеживания распределения, или подсчет используемых «единиц» памяти.

free не даст сбой, если вы «переименуете» указатель или скопируете его каким-либо образом. Однако это количество ссылок не учитывается, и только первый свободный будет правильным. Дополнительные free s являются ошибками "double free".

Попытка освободить любой указатель со значением, отличным от возвращаемого предыдущими malloc s, и как все же необъявленное - это ошибка. Невозможно частично освободить области памяти, возвращенные из malloc .

или узел в двоичном дереве, используемый для отслеживания распределения, или подсчет используемых «единиц» памяти.

free не даст сбой, если вы «переименуете» указатель или скопируете его каким-либо образом. Однако это количество ссылок не учитывается, и только первый свободный будет правильным. Дополнительные free s являются ошибками «double free».

Попытка освободить любой указатель со значением, отличным от возвращенного предыдущими malloc s, и как все же невысказанное - это ошибка. Невозможно частично освободить области памяти, возвращенные из malloc .

и только первый бесплатный будет правильным. Дополнительные free s являются ошибками «double free».

Попытка освободить любой указатель со значением, отличным от возвращенного предыдущими malloc s, и как все же необъявленное - это ошибка. Невозможно частично освободить области памяти, возвращенные из malloc .

и только первый бесплатный будет правильным. Дополнительные free s являются ошибками «double free».

Попытка освободить любой указатель со значением, отличным от возвращенного предыдущими malloc s, и как все же необъявленное - это ошибка. Невозможно частично освободить области памяти, возвращенные из malloc .

6
ответ дан 23 November 2019 в 00:19
поделиться

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

Один из типичных способов (поточный) заключается в выделении заголовка и запрашиваемой вами памяти, заполненной до некоторого минимального размера. Так, например, если вы запросили 20 байт, система может выделить 48-байтный блок:

  • 16-байтный заголовок, содержащий размер, специальный маркер, контрольную сумму, указатели на следующий/предыдущий блок и т.п.
  • 32 байта области данных (ваши 20 байт, дополненные до кратного 16).

Адрес, который затем будет вам выдан, является адресом области данных. Затем, когда вы освободите блок, free просто возьмет адрес, который вы ему дали, и, предполагая, что вы не испортили этот адрес или память вокруг него, проверит учетную информацию непосредственно перед ним. Графически это будет выглядеть примерно так:

 ____ The allocated block ____
/                             \
+--------+--------------------+
| Header | Your data area ... |
+--------+--------------------+
          ^
          |
          +-- The address you are given

Имейте в виду, что размер заголовка и подшивки полностью определяются реализацией (на самом деле, все это определяется реализацией (a), но опция встроенного учета является общей).

Контрольные суммы и специальные маркеры, существующие в учетной информации, часто являются причиной ошибок типа "Memory arena corrupted" или "Double free", если вы перезаписываете или освобождаете их дважды.

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


(a) Я писал реализации malloc во встроенных системах, где вы получали 128 байт независимо от того, что вы просили (это был размер самой большой структуры в системе), при условии, что вы просили 128 байт или меньше (запросы на большее количество возвращали значение NULL). Очень простая битовая маска (т.е. не встроенная) использовалась, чтобы решить, будет ли выделен 128-байтовый кусок или нет.

Другие разработанные мною варианты имели различные пулы для 16-байтовых блоков, 64-байтовых блоков, 256-байтовых блоков и 1K блоков, снова используя битовую маску для решения, какие блоки используются или доступны.

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

132
ответ дан 23 November 2019 в 00:19
поделиться
Другие вопросы по тегам:

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