Правила программирования на Си и Си++

       

Помещайте код, динамически распределяющий и освобождающий память, в одном и том же месте


Утечки памяти — выделенную память забыли освободить — являются большой проблемой в приложениях, продолжительность работы которых не ограничена: серверах баз данных, торговых автоматах, операционных системах и так далее. Имеется множество способов для того, чтобы отслеживать эту проблему. Многие программы, например, модифицируют функцию malloc() для создания списка выделенных областей памяти, который может просматриваться функцией free() для проверки задействованных указателей. Вы также можете доработать заголовочный файл, необходимый для сопровождения списка выделенных областей памяти, путем помещения туда информации о том, откуда было произведено выделение памяти. (Передайте __LINE__ и _FILE__ в свою отладочную версию malloc()). Список выделенных областей памяти должен быть пуст при завершении работы программы. Если он не пуст, то вы можете его просмотреть и, по крайней мере, разобраться, где была выделена эта память.

Отслеживание —

это хорошо, но предупреждение лучше. Если есть возможность, то вы должны размещать free() в той же функции, где сделан соответствующий вызов malloc(). Например, используйте это:

void user( void )            // пользователь

{

    p = malloc( size );

    producer( p );            // изготовитель

    consumer( p );            // потребитель

    free( p );

}

вместо этого:

void *producer( )

{



    void *p = malloc( size );

    // ...

    return p;

}

void consumer( void *p )

{

    // ...

    free( p );

}

void user( void )

{

    void *p = producer();

    consumer( p );

}

Несмотря на это, вы не сможете всегда делать подобное на Си. Например, предыдущие правила о неинициализированных переменных относятся и к памяти, выделенной malloc(). Лучше сделать так:

some_object *p = allocate_and_init(); // Не возвращает значения,

                                      // если памяти недостаточно.

чем так:

some_object *p = malloc( sizeof(some_object) );

if( !p )

    fatal_error("Недостаточно памяти!")

init();

В Си++  эта проблема решается при помощи конструкторов.



Содержание раздела