Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
DARKPALADIN
7 / 7 / 8
Регистрация: 19.06.2016
Сообщений: 134
Завершенные тесты: 3
1

Как free освобождает память, выделенную через malloc?

07.03.2018, 15:30. Просмотров 506. Ответов 11
Метки нет (Все метки)

Как функция free(void*) освобождает память выделенную malloc().
Если в malloc передавая размер malloc() знает сколько байт нужно выделить.
А в free() мы не передаем размер уничтожаемого блока, откуда free знает сколько байт нужно освободить?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.03.2018, 15:30
Ответы с готовыми решениями:

Нужно, чтобы память под массив выделялась не через: new — delete, а через оператор malloc (calloc) — free
Ребят, есть программа, которая работает, но нужно, чтобы память под массив выделялась не через :...

Как освободить память выделенную в подпрограмме
Имеется функция создания элемента списка struct list_int* create_elem(int num, int sqnum) { ...

Как освободить динамически выделенную память в структуре
Заголовочный файл myheader.h struct tagDate { int yy, mm, dd; }; struct tagGoods...

Освобождает ли realloc память?
Вот у нас есть стандартная функция void * realloc( void * ptrmem, size_t size ) Как известно,...

Собственная реализация malloc, free
Нужно написать собственную реализацию malloc, free без использования calloc и всего подобного. Где...

11
COKPOWEHEU
1327 / 960 / 219
Регистрация: 09.09.2017
Сообщений: 3,960
07.03.2018, 16:14 2
Если правильно помню, для этого используется несколько байтов перед официально выделенной памятью. То есть по факту выделяется не N байт а S+N байт, S перед указателем и N после.
В любом случае это только один из вариантов реализации: может просто храниться список размеров выделенных блоков.
В общем-то особенности реализации должны волновать только разработчиков компилятора
0
DARKPALADIN
7 / 7 / 8
Регистрация: 19.06.2016
Сообщений: 134
Завершенные тесты: 3
07.03.2018, 16:15  [ТС] 3
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
В общем-то особенности реализации должны волновать только разработчиков компилятора
Мне для общего развития понимать, что да как выделяется и удаляется.
0
HighPredator
5697 / 2018 / 723
Регистрация: 10.12.2010
Сообщений: 5,794
Записей в блоге: 3
07.03.2018, 16:47 4
Implementation-dependent. Или как по-русски заметили выше, зависит от того, как конкретная версия libc была сделана разрабочиками компилятора. Вот например как сделано в glibc версии 2.21 (прямо из сорца скопировал):
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
  This struct declaration is misleading (but accurate and necessary).
  It declares a "view" into memory allowing access to necessary
  fields at known offsets from a given base. See explanation below.
*/
 
struct malloc_chunk {
 
  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */
 
  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;
 
  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};
 
 
/*
   malloc_chunk details:
 
    (The following includes lightly edited explanations by Colin Plumb.)
 
    Chunks of memory are maintained using a `boundary tag' method as
    described in e.g., Knuth or Standish.  (See the paper by Paul
    Wilson [url]ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps[/url] for a
    survey of such techniques.)  Sizes of free chunks are stored both
    in the front of each chunk and at the end.  This makes
    consolidating fragmented chunks into bigger chunks very fast.  The
    size fields also hold bits representing whether chunks are free or
    in use.
 
    An allocated chunk looks like this:
 
 
    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Size of previous chunk, if allocated            | |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Size of chunk, in bytes                       |M|P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             User data starts here...                          .
        .                                                               .
        .             (malloc_usable_size() bytes)                      .
        .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Size of chunk                                     |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 
    Where "chunk" is the front of the chunk for the purpose of most of
    the malloc code, but "mem" is the pointer that is returned to the
    user.  "Nextchunk" is the beginning of the next contiguous chunk.
 
    Chunks always begin on even word boundaries, so the mem portion
    (which is returned to the user) is also on an even word boundary, and
    thus at least double-word aligned.
 
    Free chunks are stored in circular doubly-linked lists, and look like this:
 
    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Size of previous chunk                            |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `head:' |             Size of chunk, in bytes                         |P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Forward pointer to next chunk in list             |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Back pointer to previous chunk in list            |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Unused space (may be 0 bytes long)                .
        .                                                               .
        .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `foot:' |             Size of chunk, in bytes                           |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
    The P (PREV_INUSE) bit, stored in the unused low-order bit of the
    chunk size (which is always a multiple of two words), is an in-use
    bit for the *previous* chunk.  If that bit is *clear*, then the
    word before the current chunk size contains the previous chunk
    size, and can be used to find the front of the previous chunk.
    The very first chunk allocated always has this bit set,
    preventing access to non-existent (or non-owned) memory. If
    prev_inuse is set for any given chunk, then you CANNOT determine
    the size of the previous chunk, and might even get a memory
    addressing fault when trying to do so.
 
    Note that the `foot' of the current chunk is actually represented
    as the prev_size of the NEXT chunk. This makes it easier to
    deal with alignments etc but can be very confusing when trying
    to extend or adapt this code.
 
    The two exceptions to all this are
 
     1. The special chunk `top' doesn't bother using the
    trailing size field since there is no next contiguous chunk
    that would have to index off it. After initialization, `top'
    is forced to always exist.  If it would become less than
    MINSIZE bytes long, it is replenished.
 
     2. Chunks allocated via mmap, which have the second-lowest-order
    bit M (IS_MMAPPED) set in their size fields.  Because they are
    allocated one-by-one, each must contain its own trailing size field.
 
*/
Добавлено через 1 минуту
Это описание модели работы с памятью, которая применяется аллокаторами/деаллокатором.
2
07.03.2018, 16:47
liv
1166 / 971 / 199
Регистрация: 07.10.2015
Сообщений: 3,106
Завершенные тесты: 1
07.03.2018, 17:07 5
DARKPALADIN, free() выделяет не абстрактную память, а память в "куче", т.е. в специально выделенном участке памяти.
Кроме собственно выделенного участка, там строятся специальные структуры, которые определяют и размер, и другую важную информацию.
Соответственно, free() обращается куда надо и получает всё, что необходимо.
0
MrGluck
Форумчанин
Эксперт CЭксперт С++
8121 / 4973 / 1436
Регистрация: 29.11.2010
Сообщений: 13,456
07.03.2018, 17:36 6
https://habrahabr.ru/company/mailru/blog/281497/
1
Evg
Эксперт CАвтор FAQ
19874 / 7505 / 572
Регистрация: 30.03.2009
Сообщений: 20,950
Записей в блоге: 30
07.03.2018, 19:27 7
Здесь приводил схематический пример realloc и вызов конструктора
Правда в скрытой области я разместил только магическое число. Но ничего не мешает туда поместить размер выделенной области
1
DARKPALADIN
7 / 7 / 8
Регистрация: 19.06.2016
Сообщений: 134
Завершенные тесты: 3
07.03.2018, 21:50  [ТС] 8
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Если правильно помню, для этого используется несколько байтов перед официально выделенной памятью.
Вы правы, в visual studio повыделял памяти итог(заглянул в окошко памяти):
C
1
2
3
4
5
6
7
8
int* a = (int*)malloc(sizeof(int));
/*
0x02000000 FD    FD    FD   FD
0x02000004 CD    CD   CD   CD
0x02000008 FD    FD    FD   FD
 
int* a - указывает на 0x02000004
*/
то есть FDFDFDFD (блок памяти) FDFDFDFD это и есть выделенная память...
0
MrGluck
Форумчанин
Эксперт CЭксперт С++
8121 / 4973 / 1436
Регистрация: 29.11.2010
Сообщений: 13,456
07.03.2018, 23:43 9
DARKPALADIN, да. VS в дебаге и правда помечает блоки выделенной памяти с помощью данных чисел для удобства отладки.
0
DARKPALADIN
7 / 7 / 8
Регистрация: 19.06.2016
Сообщений: 134
Завершенные тесты: 3
07.03.2018, 23:48  [ТС] 10
MrGluck, Если я в функции выделяю память под некоторую переменную, в случае выхода из функции я должен очистить эту память, а также указателю на этот блок присвоить NULL?

C
1
2
3
4
5
6
7
8
9
10
11
12
void func(){
   int* i = (int*)malloc(sizeof(int));
   ....
   if(...) {
        free(i); //Ну раз это Си то он себя не почистит
        i = NULL; //Зачем так  делать?
        return;
    }
   ....
   free(i); //Ну раз это Си то он себя не почистит
   i = NULL; //Зачем так  делать?
}
0
FerrariF70
3 / 2 / 2
Регистрация: 04.02.2017
Сообщений: 170
08.03.2018, 02:26 11
Цитата Сообщение от DARKPALADIN Посмотреть сообщение
Если я в функции выделяю память под некоторую переменную, в случае выхода из функции я должен очистить эту память
если функция не возвращает эту выделенную память то надо очищать в самой функции.
0
COKPOWEHEU
1327 / 960 / 219
Регистрация: 09.09.2017
Сообщений: 3,960
08.03.2018, 08:23 12
Сформулируем по-другому: когда надобность в данном блоке памяти отпадает, программист должен освободить ее сам. Присвоение указателю NULL используется чтобы любое случайное обращение к памяти по этому указателю приводило к вылету - это лучше, чем портить данные. Ну и позволяет проверять выделена ли память по этому указателю, при соблюдении этого соглашения, естественно.
В вашем примере это не обязательно, разве что для развития хороших привычек.
0
08.03.2018, 08:23
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.03.2018, 08:23

Как корректно очистить память, которая была выделена с помощью malloc?
Добрый день. Как корректно очистить память, которая была выделена с помощью malloc? Приведу код: ...

При использовании malloc и free, приложение прекращает свою работу
Доброго времени суток, коллеги. Столкнулся с такой проблемой. При использовании malloc и free,...

Почему так себя ведёт программа? Функции: malloc(), realloc(), free()
Почему большинство значений в output 0 и несколько из значений не равно 0? /* *...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru