Почему я должен использовать свободный на указателе, но не нормальном объявлении?

library(tidyverse)

test %>% 
  mutate(place_names = map(place_names, unlist)) %>%     # update to a list of character values
  unnest() %>%                                           # unnest that columns
  group_by(Address) %>%                                  # for each address
  summarise(name = paste0(place_names, collapse = ", ")) # combine names


# # A tibble: 100 x 2
#   Address                   name                                                                                  
#   <chr>                     <chr>                                                                                 
# 1 00 RT 104, Irondequoit    Irondequoit - Wayne County Expressway, Irondequoit Bay Bridge, Bay Bridge             
# 2 00 RT 104, Webster        Empire Visionworks                                                                    
# 3 1000 E HENRIETTA RD, Bri~ Brighton, Pioneer Hall, Alexander Hall, Samuel J. Stabins Physical Education Complex,~
# 4 1000 RIDGE RD, Webster    No Match                                                                              
# 5 1200 BROOKS AV, Rochester Rochester, Dunkin'                                                                    
# 6 1200 MARKETPLACE DR, Hen~ Jackson Hewitt Tax Service, Walmart Grocery Pickup and Delivery                       
# 7 1341 WESTFALL RD, Bright~ Brighton                                                                              
# 8 1425 PORTLAND AV, Roches~ Rochester, Laboratory Service Center - Rochester General Hospital, Imelda C MacDonald~
# 9 1490 HUDSON AV, Rochester Rochester, Walmart Supercenter, Jackson Hewitt Tax Service, West Irondequoit          
# 10 1555 LONG POND RD, Greece Timothy R. McCormick Transitional Care Center at Park Ridge Living Center, Unity Hosp~
# # ... with 90 more rows
12
задан Ólafur Waage 9 March 2009 в 17:24
поделиться

8 ответов

Нормальные объявления помещаются на стек. Когда функция возвращается, указатель вершины стека возвращается к значению, которое это имело, прежде чем функция была вызвана, таким образом, память автоматически исправлена.

Находящиеся в Malloc объявления выделяются от '"кучи"', которая требует, чтобы программист справился с выделениями и освобождением.

27
ответ дан 2 December 2019 в 03:14
поделиться

Поскольку язык позволяет нам, Вы выбираете между стеком и "кучей".

Причины, почему Вы хотели бы выбрать между стеком и "кучей":

  • Переменные на "куче" намеренно не освобождаются так, чтобы можно было использовать их мимо объема блока кода или функции.
  • Более эффективно работать со стеком по сравнению с "кучей"
  • На большинстве компиляторов Вы не можете выбрать размер объекта или массива на стеке во времени выполнения, таким образом, "куча" использовалась бы здесь.

Почему "куча" не может быть автоматически освобождена:

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

Больше на стеке по сравнению с "кучей":

Язык C позволяет нам, Вы выбрали, хотите ли Вы определить свои переменные на стеке или "куче".

  • Переменные на стеке автоматически освобождены, когда они падают из объема.
  • Переменные на "куче" автоматически не освобождены.

malloc создают переменные на "куче". Простое объявление, такое как интервал x; создает переменную на стеке.

См. дополнительные материалы для чтения на стеке по сравнению с "кучей" в моем ответе здесь.

Указатели:

Просто для уточнения: переменные Указателя создаются на стеке, и они содержат адрес памяти к данным, выделенным на "куче". Они берут 4 байта на стеке в 32-разрядной системе и 8 байтов на стеке в 64-разрядной системе.

8
ответ дан 2 December 2019 в 03:14
поделиться

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

int a = 3;
int* p = &a;

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

12
ответ дан 2 December 2019 в 03:14
поделиться

Нужно отметить, что C не имеет никакого понятия стека или "кучи", хотя предыдущие ответы составляют корректный ~99% времени и дают большое понимание.

C определяет три продолжительности хранения для объектов: статичный, автоматический и выделенный. (§6.2.4.1)

Статические объекты (такие как глобальные переменные) доступны для продолжительности всей программы.

Автоматические объекты существуют, пока их переменная находится в объеме. Они прекращают существование, как только это выходит из объема.

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

Строго говоря Вы не должны называть свободными (). Или возможно Вы делаете (необходимо было бы прочитать стандарт для точки authoritive на этом), но Вы могли сделать все это в конце основного (), непосредственно перед тем, как программа завершается. Или, предоставьте операционной системе право делать это для Вас (который большинство, если не все, делает.), Но это снова было бы оконечностью - объекты появляются, когда Вы называете malloc (), выходите, когда Ваша программа завершается.

Мне не придется говорить подробно о практических последствиях здесь: Память конечна. Можно только выделить столько байтов, прежде чем у Вас закончится память. Используя статические объекты для всего было бы слишком расточительно; попытка снова использовать блоки или один большой блок статического ЗУ была бы трудна и в любом случае аналогична динамическому подходу выделения. Используя автоматическое хранение для долговечных объектов вынудил бы Вас сделать их объем максимально большим, примерно соответствуя тем из статических объектов так или иначе.

--

Теперь, некоторые примечания:

{
    int *temp = malloc(sizeof(int));
    *temp = 5;
    //free(temp);
}

Отметьте это temp вот автоматический объект. Это будет только жить пока его объем, который заканчивается в}. Объект, на который это указывает, однако, выделяется. Это будет существовать, пока Вы не назовете свободными () на его адресе. С тех пор temp содержит единственную копию того адреса, Вы потеряете шанс назвать свободным () однажды temp выходит из объема. Некоторая память будет постоянно выделена, все же недоступная. Это называют утечкой памяти.

Сборка "мусора" является другим методом для управления хранением объектов. Реализация в C могла бы быть похожей:

{
    int *temp = gc_malloc(sizeof(int));
    *temp = 5;
}

Где в}, компьютер решил бы что последняя ссылка, temp, к выделенному объекту был потерян и что это будет хорошая идея освободить его.

Это - компромисс, где Вы не должны волновать по поводу свободного () объекты луга (который не является незначительной вещью, поскольку простые примеры могли бы заставить Вас думать), но где gc_malloc () здесь более сложен, чем простой malloc (), и существует невидимый код, выполняющийся в этом} где temp выходит из объема. И это - совершенно другая тема, как компьютер мог бы решить это temp была последняя ссылка. (Некоторые практические решения могли бы вовлечь Вас пишущий больше кода вокруг "интервала *временный файл".)

5
ответ дан 2 December 2019 в 03:14
поделиться

Alnitak корректен. Я хотел бы указать на то, что "на стеке" действительно означает.

Когда программа сделает вызов функции, она ожидает, что функция сделает некоторый объем работы, затем возвратится и продолжится к следующей строке кода. Функция не имеет никакого способа знать, куда возвратиться, когда функция завершена. Так, машина имеет стек вызовов для каждой программы, используемой для продвижения адреса следующего утверждения в программе прежде, чем вызвать функцию. Оператор "возврата" просто выталкивает адрес программы и переходы к нему.

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

Напротив, вызов malloc() выделяет память от "кучи", которая явно откладывает память для программы и остается в объеме столько, сколько программа работает. Таким образом, если Вы не делаете free() память, это останется выделенным и рассмотрело утечку памяти.

3
ответ дан 2 December 2019 в 03:14
поделиться

В дополнение к точкам, сделанным этим сообщением, разъясняет вещи далее.

0
ответ дан 2 December 2019 в 03:14
поделиться

Это - очень хороший вопрос, в то время как многие ответили бы, что вот в чем разница между стеком и выделением "кучи", фундаментальный ответ под лежащей системой, выставил что-то Вам, что это не было должно.

При выделении памяти Вам не придется волноваться о возвращении ее. Система должна быть достаточно умной, чтобы выяснить, что у Вас нет доступа (точка или ссылка) к ней больше, поэтому она может автоматически забрать память.

Более новые языки как Java и C# сделали это.

-9
ответ дан 2 December 2019 в 03:14
поделиться

Потребность к free() не зависит от того, объявили ли Вы указатель, а скорее имеете ли Вы malloc()память редактора.

Как Brian Bondy, сказанный прежде, переменные ("int number", "char string[10]", "float your_boat", и т.д.), уходят, когда затем падают из объема, как то, когда Ваш код оставляет функциональный блок. Так указатель в Вашем вопросе ("temp"), не уходит, когда Вы звоните free() - скорее безотносительно Вашего кода, выделенного, когда это звонило malloc() уходит. Ваш указатель все еще остается там, т.е. сразу после Вашего примера кода, который Вы могли сказать"temp = &some_other_variable"не имея необходимость говорить (снова)"int *temp;".

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

int * temp = (int*)malloc(sizeof(int));

без более позднего высказывания

free(temp);

Но это не путь malloc() реализован.

2
ответ дан 2 December 2019 в 03:14
поделиться
Другие вопросы по тегам:

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