[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]

Программирование: Разработка и отладка программ


Отладчик функций malloc

Отладка приложений, в которых возникают проблемы с распределением памяти с помощью функции malloc(), очень часто требует больших усилий и не всегда дает желаемые результаты. Чаще всего проблемы бывают вызваны записью данных за границами выделенного буфера. Такая операция не влечет за собой немедленных последствий, и ошибка возникает только на этапе, когда потребуются данные, которые хранились в ошибочно занятой области памяти ранее.

Подсистема управления памятью AIX снабжена отладчиком, позволяющим отслеживать ситуации ошибочной совместной записи и чтения одних и тех же областей памяти, а также операции повторного освобождения и выделения одних и тех же областей памяти с помощью функции malloc(). Управление отладчиком осуществляется в момент запуска процесса с помощью переменных MALLOCTYPE и MALLOCDEBUG.

Если отладчик обнаруживает ошибку, он в большинстве случаев выполняет функцию abort() или передает сигнал нарушения сегментации (SIGSEGV). Как правило, при обнаружении ошибки приложение немедленно останавливается, и создается файл core.

Отладчик может применяться только с программами, использующими стандартные средства распределения памяти. Отладчик не поддерживает malloc для AIX версии 3.1.

Включение отладчика malloc

По умолчанию отладчик malloc выключен. Для того чтобы настроить и включить его, нужно задать следующие переменные среды:

 
MALLOCTYPE

 
MALLOCDEBUG

Для запуска отладчика malloc с параметрами по умолчанию нужно задать переменную MALLOCTYPE:

 
MALLOCTYPE=debug

Для включения отладчика с нестандартными параметрами нужно задать обе переменные MALLOCTYPE и MALLOCDEBUG:

 
MALLOCTYPE=debug

 
MALLOCDEBUG=опции

где опции - список опций конфигурации через запятую.

Если отлаживаемая программа часто вызывает функцию malloc(), то может быть полезным увеличить объем памяти, доступный программе, с помощью команды ulimit или команды ld с опцией -bmaxdata. Подробная информация об этом приведена в разделе "Дисковая и оперативная память" далее в этой главе.

Опции MALLOCDEBUG

С помощью переменной MALLOCDEBUG можно задать следующие опции конфигурации отладчика malloc:

Все эти опции подробно описаны ниже.

Переменная MALLOCDEBUG должна быть задана в следующем формате:

 

MALLOCDEBUG=[[ align:n | postfree_checking | validate_ptrs | 
               override_signal_handling | allow_overreading | 
               report_allocations | record_allocations],...]
			

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

 

MALLOCDEBUG=align:0,validate_ptrs,report_allocations
			

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

Переменная MALLOCDEBUG применяется только в случае, если переменной MALLOCTYPE присвоено значение "debug":

 
MALLOCTYPE=debug

 
MALLOCDEBUG=align:2,postfree_checking,override_signal_handling

Ниже подробно описаны все опции MALLOCDEBUG:

align:n

По умолчанию функция malloc() выравнивает возвращаемый указатель по границе ячейки размером в 2 слова (в 64-разрядном режиме - 4 слова). С помощью опции align:n можно изменить задать другой режим выравнивания. Значение n задает размер ячейки для выравнивания в байтах и может принимать любые значения, равные степеням 2, в диапазоне от 0 до 4096, или значение 0 (0, 1, 2, 4 и т.д.). Значения 0 и 1 интерпретируются одинаково и означают отсутствие выравнивания (т.е. любое обращение к памяти за границами выделенной области приведет к вызову функции abort()).

Примечания:
  1. Более подробные сведения об опции align:n приведены в разделе "Дополнительная информация об опции align:n" да лее в этой главе.
  2. Выравнивание по границе ячеек в 1 слово соответствует значению align:4.
  3. Программы, в которых применяются компоненты DCE, должны использовать значение align:8. Применение других значений может привести к непредсказуемым результатам.

postfree_checking

По умолчанию подсистема malloc позволяет обращаться к областям памяти, которые были освобождены. Ответственность за это возлагается на программу, обращающуюся к памяти. Если вы укажете опцию postfree_checking, то любое обращение к памяти, которая уже освобождена, приведет к завершению работы программы, а отладчик выдаст сообщение об ошибке. При этом будет создан файл core.

Примечание:
  1. Если вы укажете опцию postfree_checking, то будет автоматически включена опция validate_ptrs.

validate_ptrs

По умолчанию функция free() не проверяет входные значения, и поэтому не выдает ошибок при попытке освободить память, которая не была выделена с помощью функции malloc(). Если в функцию free() будет передано значение NULL, то вернет управление, не выполняя никаких действий. Если ей будет передан недопустимый параметр, то результаты ее выполнения будут непредсказуемы. Возможно, будет создан файл core, но это зависит от конкретного значения параметра. Если для отладчика будет указана опция validate_ptrs, то функция free() будет проверять входные параметры. Если параметр окажется недопустимым (например, будет указывать на область данных, которая не выделалась ранее с помощью команды malloc() или realloc()), то отладчик malloc выдаст сообщение об ошибке. После этого работа процесса будет завершена с созданием файла core с помощью функции abort().

override_signal_handling

Отладчик malloc различает два вида ошибок:

 

  1. Ошибки при обращении к памяти (например, попытки чтения или записи за границами выделенной памяти) - в этом случае выдается сигнал нарушения сегментации (SIGSEGV) и создается файл core.
  2. Прочие ошибки (например, попытки повторно освободить область памяти) - в этом случае отладчик выдает сообщение об ошибке и вызывает функцию abort(), которая завершает процесс с помощью сигнала SIGIOT.


Если вызывающая программа блокирует или перехватывает сигналы SIGSEGV и SIGIOT, то отладчик не сможет сообщать об ошибках. Для таких ситуаций предусмотрена опция override_signal_handling.

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

 

  1. Отключать все обработчики сигналов программы.
  2. Восстанавливать стандартные обработчики сигналов SIGIOT и SIGSEGV (SIG_DFL).
  3. Разблокировать сигналы SIGIOT и SIGSEGV.


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

Примечания:
  1. Опция override_signal_handling неэффективна при работе с приложениями с несколькими нитями, поскольку отладчик пользуется функцией sigprocmask(), при том что многие многонитевые приложения пользуются функцией pthread_sigmask().
  2. Если нить программы вызывает функцию sigwait(), не включая SIGSEGV и SIGIOT в набор сигналов, и отладчик обнаружит ошибку в такой нити, то нить зависнет, поскольку отладчик может генерировать только сигналы SIGSEGV и SIGIOT.
  3. Если в функцию ядра будет передан недопустимый указатель, то в функции ядра возникнет ошибка. Как правило, в таких ситуациях функции ядра возвращают код ошибки EFAULT. Если программа не проверяет коды возврата системных вызовов, то такие ошибки могут проходить незамеченными.

allow_overreading


Если программа пытается прочитать данные из области за концом выделенного участка памяти, по умолчанию отладчик выдает сигнал нарушения сегментации и создает файл core. Если вы укажете опцию allow_overreading, то отладчик будет игнорировать такие ошибки.

report_allocations

Если будет указана опция report_allocations, отладчик будет сохранять список активных выделенных областей памяти на момент завершения работы программы. Активными называются области памяти, которые не были освобождены на момент завершения работы программы. Для каждой области будет указана та же информация, что и для опции record_allocations.

Примечания:
  1. Если вы укажете опцию report_allocations, то будет автоматически включена опция record_allocations.
  2. Для любой программы будет показана по крайней мере одна активная область, соответствующая обработчику atexit(), создающему данный отчет.

record_allocations

Если будет указана опция record_allocations, отладчик будет сохранять сведения обо всех вызовах функции malloc(). Для каждого вызова будет сохраняться следующая информация:

 


Информация о выделенной области памяти хранится до тех пор, пока эта область не будет освобождена.

Дополнительная информация об опции align:n

Следующая формула позволяет определить, какой критерий будет применяться отладчиком при выделении памяти и определении допустимости запросов на чтение и запись данных. Здесь размер - это размер выделяемой области памяти в байтах, а n - значение опции MALLOCDEBUG=align:n:

((((размер / n) + 1) * n) - размер) % n

Следующие примеры иллюстрируют зависимость между значением опции align:n и тем, насколько далеко за границу выделенной области памяти отладчик разрешит заходить программе:

  1. В следующем примере опции align присвоено значение 2:

    	MALLOCTYPE=debug
    	MALLOCDEBUG=align:2,postfree_checking,override_signal_handling
    

    Отладчик будет действовать следующим образом:

     


  2. В следующем примере опции align присвоено значение 0:

    	MALLOCTYPE=debug
    	MALLOCDEBUG=align:0,postfree_checking,override_signal_handling
    

    В данном случае программе будет запрещено выходить за границу выделяемой области вне зависимости от ее размера.

Выходные данные отладчика

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

Как правило, при обнаружении ошибки приложение немедленно останавливается, и создается файл core. Если ошибка вызвана попыткой чтения или записи данных за границей выделенной области памяти, то сигнал о нарушении сегментации будет выдан на инструкции, вызвавшей обращение к памяти. Если ошибка будет обнаружена одной из функций работы с памятью (malloc(), free(), realloc() или calloc()), то будет показано сообщение об ошибке и вызвана функция abort().

Производительность

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

Дисковая и оперативная память

Со включенным отладчиком подсистеме malloc требуется существенно больше памяти для работы. На выполнение каждого запроса malloc() дополнительно расходуется такое количество страниц памяти, в которое можно уместить "4096+2*sizeof(unsigned long)". Это может вызывать серьезные проблемы при работе с большими программами, но отладка большинства приложений не сильно скажется на расходе памяти.

Если отлаживаемая программа часто вызывает функцию malloc(), это может привести к серьезному расходу памяти и сделать невозможным нормальное выполнение программы в пределах одного сегмента. В таких случаях может быть полезным увеличить объем памяти, доступный программе, с помощью команды ulimit или команды ld с опцией -bmaxdata.

При выполнении программ с отладчиком следует задать ограничения ulimit для данных (-d) и стека (-s) следующим образом:

	ulimit -d unlimited 
	ulimit -s unlimited 

Опции -bmaxdata следует присвоить значение 0x80000000 - в этом случае процессу будет доступен максимальный возможный объем памяти (8 сегментов для 32-разрядного процесса).

После отключения отладчика следует восстановить исходные значения ulimit и -bmaxdata.

Команда ulimit и опция -bmaxdata подробно описаны в разделе Глава 8, Поддержка программ большого объема.

Ограничения

Отладчик может применяться только с программами, использующими стандартные средства распределения памяти. Отладчик не поддерживает malloc для AIX версии 3.1.

Отладчик не рассчитан на постоянное применение. Хотя он спроектирован таким образом, чтобы минимизировать снижение производительности системы, такое снижение все же может быть существенным при широком применении отладчика. В частности, если вы укажете MALLOCTYPE=debug в файле /etc/environment (для применения отладчика для всех процессов системы), то скорее всего стабильная работа системы будет нарушена (например, из-за постоянных обращений к пространству подкачки). Отладчик следует применять только в тех случаях, когда это действительно необходимо.

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

Примером такой программы может служить сервер X, выполняющий огромное количество запросов на выделение очень маленьких участков памяти во время инициализации и в ходе дальнейшей работы. Попытка запустить сервер X с отладчиком (с помощью команды X или xinit) неминуемо приведет к аварийному завершению сервера X из-за недостатка памяти. Это известное ограничение отладчика. В то же время большинство клиентов X можно без проблем запускать с отладчиком. Для запуска клиента X с отладчиком выполните следующие действия:

  1. Запустите сервер X без отладчика.
  2. Откройте окно терминала (например, dtterm, xterm или aixterm).
  3. Задайте нужные переменные среды в окне терминала.
  4. Запустите клиент X из этого терминала.

Связанная информация

Глава 8, Поддержка программ большого объема

Функции malloc, free, realloc, calloc, mallopt, mallinfo, alloca и valloc в книге AIX 5L Version 5.1 Technical Reference: Base Operating System and Extensions Volume 1.


[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]