2010-12-04 5 views
1

Я попытался найти учебное пособие, в котором явным образом объясняется, какие вещи нужно учитывать при освобождении памяти. Но я не мог найти такие вещи. Кто-нибудь может сообщить мне, какие основные вещи программист должен иметь в виду, дезактивируя память в C. В настоящее время я имею дело со связанными списками. Есть некоторые случаи, когда новый связанный список создается с использованием 2 или более существующих связанных list.For Например:Каковы основные моменты, которые следует учитывать при освобождении памяти в C?

list l1; 
list l2 
list l3 = list_append(l1,l2) 
list l4 = list_append(l3,l1) 
list l5 = list_append(l3,l4) 

Какова последовательность открепления, что я должен следовать, чтобы освободить память?

здесь list_append - это функция, которая возвращает копию списка.

+2

Невозможно сказать, не зная, что делает `list_append`. Копирует ли эти списки или просто связывает их вместе? – 2010-12-04 17:29:17

+0

@ Составите список, который добавляет копии входных списков. – thetna 2010-12-04 17:32:53

ответ

3

При использовании семейства функций malloc/free необходимо соблюдать два правила.

  1. Вы можете только free пригодной память возвращаемого malloc семьи распределителя, и освобождая его делаешь его недействительным (так двойное освобождение ошибки как освобождение память не получается из таНос).
  2. Это ошибка доступа к памяти после ее освобождения.

А вот важная часть: аллокатор не предоставляет не средства, чтобы помочь вам выполнять эти правила.

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

Позвольте мне предложить две модели, которые достаточно безопасны:

Выделяют и свободными в том же контексте

//... 
{ 
    SomeData *p = malloc(sizeof SomeData); 
    if (!p) { /* handle failure to allocate */ } 
    // Initialize p 

    // use p various ways 

    // free any blocks allocated and assigned to members of p 
    free p; 
} 
//... 

Здесь вы знаете, что данные р указывает на выделяется один раз и освободила один раз и используется только между. Если инициализация и освобождение содержимого SomeData является нетривиальными вы должны обернуть их в паре функций, так что это сводится к

//... 
{ 
    SomeData *p = NewSomeData(i,f,"name"/*,...*/); // this handles initialization 
    if (!p) { /* handle failure to allocate */ } 

    // use p various ways 


    ReleaseSomeData(p) // this handles freeing any blocks 
        // allocated and assigned to members of p 
} 
//... 

Зова это один «Сфера собственность». Вы заметите, что он не сильно отличается от локальных автоматических переменных и предоставляет вам только несколько параметров, недоступных с автоматическими переменными .

Вызов второй вариант «Структура собственности»: Здесь ответственность за удаление выделенного блока вручается в большей структуре:

List L = NewList(); 
//... 

while (something) { 
    // ... 
    Node n= NewNode(nodename); 
    if (!n) { /* handle failure to allocate */ } 
    ListAdd(L,n);    // <=== Here the list takes ownership of the 
           // node and you should only access the node 
           // through the list. 
    n = NULL; // This is not a memory leak because L knows where the new block is, and 
      // deleting the knowledge outside of L prevents you from breaking the 
      // "access only through the structure" constraint. 
    //... 
} 

// Later 
RemoveListNode(L,key); // <== This routine manages the deletion of one node 
         // found using key. This is why keeping a separate copy 
         // of n to access the node would have been bad (because 
         // your separate copy won't get notified that the block 
         // no longer valid). 

// much later 
ReleaseList(L); // <== Takes care of deleting all remaining nodes 

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

1

Первый принцип:

Что бы вы выделить (с calloc/ таНос) вам нужно освободить в конце концов.

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

2

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

  1. То, что память выделяется динамически, в первую очередь
  2. что после открепления не пытаться использовать память снова
  3. Чтобы вы сохраняли хотя бы один указатель на выделение до тех пор, пока вам не понадобится освободить его (т. е. не позволяйте вашей единственной ссылке на блок выйти из области действия или быть уничтожены).

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

Третье требование особенно важно в сложных структурах данных, где выделенная память может содержать структуры, которые сами содержат указатели на выделенную память. Разумеется, вам необходимо освободить их до освобождения структуры более высокого уровня.

2

Может кто-нибудь, дайте мне знать, каковы основные вещи, которые программист следует иметь в виду при deallocting памяти в C.

Основные принципы довольно просты: любой памяти, выделенной с помощью семейство функций * alloc, в том числе malloc, calloc или realloc, должно быть освобождено по соответствующему вызову free().

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

0

Используйте valgrind (1), чтобы показать в вашем конкретном случае, какие объекты по-прежнему существуют при завершении, а затем изменить код, чтобы освободить ненужные.

0

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

Смежные вопросы