Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / Pascal и Delphi / Учебник по Delphi 5 / Тестирование и отладка /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Силовая отладка - Программирование от RIN.RU
Силовая отладка



Вывод на консоль


Еще один способ вывода отладочной информации- вывод на консоль с использованием процедур Write и WriteLn. Вы можете конвертировать проект в консольное приложение, например, выбрав соответствующую опцию (команду Project/Options, вкладку Linker и опцию Generate Console Application) или поместив директиву $APPTYPE CONSOLE в главный DPR-файл. Учитывая, что ваше приложение- не консольное, воспользуйтесь возможностями условной компиляции и используйте директиву $APPTYPE как показано ниже:


{$ifdef Debug}
{$APPTYPE CONSOLE}
{$endif}


Теперь вывод на консоль будет осуществляться только в отладочной версии вашего приложения.


Если вы попытались использовать функцию Write или WriteLn и получили сообщение об ошибке I/O Еггог, значит, вы забыли сделать проект консольным приложением.


Обратите внимание, что здесь применяется тот же код, что и раньше, но теперь мы используем вывод на консоль вместо ShowMessage. Убедитесь, что вы создаете консольное приложение, и измените обработчик так, как показано ниже.


procedure TFormI.ButtonlClick(Sender: T0bject);
var MemStat: TMemoryStatus;
begin
MemStat.dwLength:= SizeOf(TMemoryStatus);
GlobalMemoryStatus(MemStat);
with MemStat do
begin
WriteLn(Format('Memory load: %d%%',[dwMemoryLoad]));
WriteLn(Format('Total physical: %d',[dwTotalPhys]));
WriteLn(Format('Available physical: %d',[dwAvailPhys]));
WriteLn(Format('Total page file: %d',[dwTotalPageFile]));
WriteLn(Format('Available page file: %d',[dwAvailPageFile]));
WriteLn(Format('Total virtual: %d',[dwTotalVirtual]));
WriteLn(Format('Available virtual: %d',[dwAvailVirtual]));
end;
end;




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


Запись в Log-файл


Запись отладочной информации в файл протокола (Log-файл) существенно отличается от предыдущих приемов записи, так как это уже нельзя назвать "быстро и грязно". Это отличная технология, которую можно использовать в любом приложении.


Запись в файл протокола выполняется так же, как и вывод на консоль, но вместо WriteLn (. . . ) используется WriteLn (LogFile, . . . ), где LogFile - имя файловой переменной типа TextFile. Надо также не забывать открывать этот файл в начале работы приложения и закрывать - в конце. Проще всего этого добиться, поместив соответствующий код в свой модуль, который благодаря возможности условной компиляции подключается только в отладочной версии вашей программы.


Листинг 2.1. Модуль протоколирования отладочной информации.


unit uLoq;
interface
procedure Log(S: Strings-implementation uses
Windows, SysUtils;
var
LogFile: TextFile;
LogCriticalSection: TRtlCriticalSection;
procedure Log(S: String);
var
SystemTime: TSystemTime;
FileTime: TFileTime;
begin
GetSystemTime (SystemTime) ;
SystemTimeToFileTime(SystemTime, FileTime) ;
EnterCriticalSection(LogCriticalSection);
WriteLn(LogFile, Format('%s %.8x%.8x %5',
[FormatDateTime('yy.mm.dd hh.inm.ss'. Now),
FileTime.dwHighDateTime, FileTime.dwLowDateTime, S])) ;
LeaveCriticalSection(LogCriticalSection) ;
end;
procedure Startup;
var
FileName: String;
begin
InitializeCriticalSection(LogCriticalSection);
FileName := Format("Log file for %s at %s.txf,
[ParamStr(O), DateTimeToStr(Now)]) ;
while Pos(':', FileName) 0 do
FileName[Pos(':', FileName)] := '.';
while Pos('/', FileName) 0 do
FileName[Pos('/', FileName)] := '-';
while Pos('\', FileName) 0 do
FileName[Pos('\', FileName)] := '.';
AssignFile(LogFile, FileName);
Rewrite(LogFile) ;
end;
procedure Shutdown;
begin
CloseFile(LogFile) ;
DeleteCriticalSection(LogCriticalSection) ;
end;
initialization Startup;
finalization Shutdown;
end.




Этот модуль сам создает, открывает и закрывает файл протокола. Имя файла создается с учетом имени приложения и текущих даты и времени, что исключает возможность записи информации поверх существующего файла. Для использования модуля условно включите его, как показано ниже.


unit MyUnit;
interface
uses
($ifdef Debug} uLog, {$endif)
Windows, Messages, SysUtils, Classes,
. . .




Затем используйте его приблизительно так.


{$ifdef Debug)
Log(Format('Entering the Foo procedure; Bar = %d',[Bar]));
{$endif}




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


Модуль uLog обладает двумя интересными и полезными свойствами. Во-первых, каждая запись в файл предваряется информацией о дате, времени и шестнадцатеричным числом, соответствующим системному времени в миллисекундах. Эта информация может быть весьма полезной, особенно когда вы хотите отследить последовательность событий в приложении. Во-вторых, модуль использует критические разделы (critical section), что обеспечивает доступ к файлу только одной подзадачи в один момент времени.


Как правильно использовать файл протокола? Какую информацию в него записывать? Сколько программистов, столько и ответов на эти вопросы. Лично я предпочитаю придерживаться золотой середины между "записывай все" и "записывай только то, что отлаживаешь".

<<<  Назад
 1  2 


 8  Комментарии к статье  8 8  Обсудить в чате

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь