При использовании семейства функций malloc
/free
необходимо соблюдать два правила.
- Вы можете только
free
пригодной память возвращаемого malloc
семьи распределителя, и освобождая его делаешь его недействительным (так двойное освобождение ошибки как освобождение память не получается из таНос).
- Это ошибка доступа к памяти после ее освобождения.
А вот важная часть: аллокатор не предоставляет не средства, чтобы помочь вам выполнять эти правила.
Вы должны управлять им самим. Это означает, что вам необходимо упорядочить логику вашей программы, чтобы гарантировать, что эти правила всегда соблюдаются. Это с, и огромное количество утомительной и сложной ответственности сбрасывается на ваши плечи.
Позвольте мне предложить две модели, которые достаточно безопасны:
Выделяют и свободными в том же контексте
//...
{
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
Учитывая, как у вас есть список с узлами, которые будут добавлены и удалены, вы могли бы рассмотрим шаблон собственности, поэтому помните: как только вы дадите узел вашей структуры только доступ к ней через структуру.
Невозможно сказать, не зная, что делает `list_append`. Копирует ли эти списки или просто связывает их вместе? – 2010-12-04 17:29:17
@ Составите список, который добавляет копии входных списков. – thetna 2010-12-04 17:32:53