Вы не можете делать умные указатели в C, потому что он не обеспечивает необходимый синтаксис, но вы можете избежать утечек на практике. Напишите код выпуска ресурса сразу после того, как вы его выделите. Поэтому всякий раз, когда вы пишете malloc
, вы должны немедленно написать соответствующий free
в разделе очистки.
В C я часто вижу шаблон 'GOTO cleanup':
int foo()
{
int *resource = malloc(1000);
int retVal = 0;
//...
if (time_to_exit())
{
retVal = 123;
goto cleanup;
}
cleanup:
free(resource);
return retVal;
}
В C мы также используем много контекстов, которые выделяют вещи, для этого тоже можно применить то же правило:
int initializeStuff(Stuff *stuff)
{
stuff->resource = malloc(sizeof(Resource));
if (!stuff->resource)
{
return -1; ///< Fail.
}
return 0; ///< Success.
}
void cleanupStuff(Stuff *stuff)
{
free(stuff->resource);
}
Это аналог конструкторов и деструкторов объектов. Пока вы не отдадите выделенные ресурсы другим объектам, они не будут вытекать и указатели не будут болтаться.
Нетрудно написать собственный распределитель, который отслеживает выделения и записывает блоки с утечками atexit
.
Если вам нужно выдать указатели на выделенные ресурсы, вы можете создать для него контексты обертки, и каждому объекту принадлежит контекст обертки вместо ресурса. Эти обертки совместно используют ресурс и объект-счетчик, который отслеживает использование и освобождает объекты, когда его никто не использует. Вот как в C ++ 11 shared_ptr
и weak_ptr
работают. Более подробно здесь написано: Как работает weak_ptr?