Страшные памятки в коде программы...
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 21.09.04 16:25
Оценка: 13 (1) :)))
Сегодня открытие сделал Вернее, приспособил для себя более удобный способ оставлять [сабж], чтобы чего-то не забыть дописать.

Обычно я делал как?

switch(nodeType)
{
  case stringNode:
   ...
  break;

  default:
     assert(false);
  break;
} // switch

Выделенный ассерт нужен для того, чтобы чего не забыть, буде появится новый тип, который надо обработать. Но сообщение, которое выкидывает assert, уж очень неинформативное:

Assertion failed: false, file C:\JOB\Garbage\AssertionTest.cpp, line 85


Почесал я репу и придумал малой кровью велосипед

enum
{
  NOT_IMPLEMENTED
};


switch(nodeType)
{
  case stringNode:
   ...
  break;

  default:
     assert( (NOT_IMPLEMENTED >> nodeType) );
  break;
} // switch


Теперь все гораздо веселее:

Assertion failed: (NOT_IMPLEMENTED >> nodeType), C:\JOB\Garbage\AssertionTest.cpp, line 85

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

З.Ы. Почему в "Философию"? Затрудняюсь ответить Наверное потому, что данная заметка и есть частный пример философии удобно-ленивого программирования

З.З.Ы. Как там в "Юморе" говорят? Звиняйте, если байан
Re: Страшные памятки в коде программы...
От: AMogil Россия  
Дата: 21.09.04 16:58
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Сегодня открытие сделал Вернее, приспособил для себя более удобный способ оставлять [сабж], чтобы чего-то не забыть дописать.


F>З.З.Ы. Как там в "Юморе" говорят? Звиняйте, если байан


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

Что-то вроде.


Assert(Assigned(FPlace), CAssert_927C00FE_D84B_4E15_8CBF_5CCB3514C82D);

...

unit AssertsConsts
...
CAssert_927C00FE_D84B_4E15_8CBF_5CCB3514C82D = '...';


Это я так...вдруг кто-то умней делает, то может подскажут...

Алексей.
Re: Страшные памятки в коде программы...
От: Vark  
Дата: 22.09.04 00:32
Оценка:
Здравствуйте, Flamer, Вы писали:

...

Я делаю так (начиная с VS 6.0):

вынес в общедоступный h-файл объявление

#define _CMN_QUOTE(x) # x
#define CMN_QUOTE(x) _CMN_QUOTE(x)
#define CMN_MSG(msg) message(__FILE__ "(" CMN_QUOTE(__LINE__) ") : " #msg)

а потом в нужном мне месте пишу:

#pragma CMN_MSG(Change it !!!!)

и тогда каждый раз при компиляции появляется соответствующий варнинг

минус — нельзя писать по-русски
плюс — сделав двойной щелчок по варнингу, сразу оказываешся в нужном месте кода


P.S. Идея не моя , вроде у рихтера в исходниках нашел
Re: Страшные памятки в коде программы...
От: Блудов Павел Россия  
Дата: 22.09.04 02:07
Оценка: 14 (3) +3
Здравствуйте, Flamer, Вы писали:

F>Обычно я делал как?


F>
F>switch(nodeType)
F>{
F>  case stringNode:
F>   ...
F>  break;

F>  default:
F>     assert(false);
F>  break;
F>} // switch
F>

F>Выделенный ассерт нужен для того, чтобы чего не забыть, буде появится новый тип, который надо обработать. Но сообщение, которое выкидывает assert, уж очень неинформативное:

F>
F>Assertion failed: false, file C:\JOB\Garbage\AssertionTest.cpp, line 85
F>


Я обычно делаю так

switch(nodeType)
{
  case stringNode:
   ...
  break;

  default:
     assert(!"missed case in " __FUNCTION__);
  break;
} // switch
... << RSDN@Home 1.1.4 beta 2 >>
Re: Страшные памятки в коде программы...
От: S.Yu.Gubanov Россия http://sergey-gubanov.livejournal.com/
Дата: 22.09.04 07:07
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Сегодня открытие сделал


А я, когда мне надоело искать ошибки, поступил очень сурово. Представьте себе, я каждую процедуру обернул дополнительным блоком TRY EXCEPT.
PROCEDURE TMyClass.DoSmth;
BEGIN
  TRY
    ...
  EXCEPT ON e: SysUtils.Exception DO Error(e, 'TMyClass.DoSmth') END
END;

Процедура Error для каждого модуля своя:
PROCEDURE Error(e: SysUtils.Exception; CONST ProcName: STRING);
BEGIN
  Errors.Error(e, 'MyModuleName', ProcName);
END;

В модуле Errors есть процедура Error
PROCEDURE Error(CONST e: SysUtils.Exception; CONST UnitName, ProcName: STRING);
BEGIN
  IF ASSIGNED(e) THEN BEGIN
    FErrorsForm.ErrorDlg(UnitName, ProcName, e.Message);
    TRAP(UnitName + '.' + ProcName+' {' + e.Message + '}');
  END;
END;

PROCEDURE Trap(msg: STRING);
BEGIN
  RAISE SysUtils.Exception.Create(msg);
END;

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


P.S. Вот если писать прогу на Обероне под названием Component Pascal в системе BlackBox, то там при возникновении system trap (и наличии исходника) автоматически курсор устанавливается в то место где произошел сбой и показывается диалоговое окно со стеком всех процедур и со значениями локальных переменных всех процедур, то есть там, та работа, которую я в Delphi выполнял вручную, сделана автоматом.
Re[2]: Страшные памятки в коде программы...
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.09.04 09:18
Оценка:
Здравствуйте, S.Yu.Gubanov, Вы писали:

SYG>P.S. Вот если писать прогу на Обероне под названием Component Pascal в системе BlackBox, то там при возникновении system trap (и наличии исходника) автоматически курсор устанавливается в то место где произошел сбой и показывается диалоговое окно со стеком всех процедур и со значениями локальных переменных всех процедур, то есть там, та работа, которую я в Delphi выполнял вручную, сделана автоматом.


З.З.Ы. Вот если писать прогу на Java или .Net, то там при возникновении exception независимо от наличия исходника доступен полный stack trace. А IDE, где возможно, позиционирует курсор на нужную строку.
Впрочем, под отладкой позиционирование курсора выполняет и Delphi.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Страшные памятки в коде программы...
От: serg_mo  
Дата: 24.09.04 14:05
Оценка: 4 (2) +1
Здравствуйте, Sinclair, Вы писали:

S>З.З.Ы. Вот если писать прогу на Java или .Net, то там при возникновении exception независимо от наличия исходника доступен полный stack trace. А IDE, где возможно, позиционирует курсор на нужную строку.

S>Впрочем, под отладкой позиционирование курсора выполняет и Delphi.

А вот если писать прогу на VisualWorks Smalltalk, то там при возникновении Exception открывается дебаггер с полным stack trace, возможностью гулять по нему туда-сюда, сразу же доступен код метода по позиции в stack trace. И тут же можно этот код отредактиовать, а сообщение — перепослать и продолжить работу . Это, конечно, если вы в developer-режиме. В deployment-версии — только stack trace (сжатый и развернутый).

Ну, кто круче?
... << RSDN@Home 1.1.3 stable >>
Re[4]: Страшные памятки в коде программы...
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.09.04 15:42
Оценка:
Здравствуйте, serg_mo, Вы писали:

_>Ну, кто круче?

Боюсь, что не король эльфов.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Страшные памятки в коде программы...
От: Andrew Simontsev Россия  
Дата: 01.10.04 12:35
Оценка: +1
Здравствуйте, AMogil, Вы писали:

AM>

AM>Assert(Assigned(FPlace), CAssert_927C00FE_D84B_4E15_8CBF_5CCB3514C82D);

AM>...

AM>unit AssertsConsts
AM>...
AM>CAssert_927C00FE_D84B_4E15_8CBF_5CCB3514C82D = '...';
 
AM>


AM>Это я так...вдруг кто-то умней делает, то может подскажут...


ATL-ный подход:

ATLASSERT(bCondition && _T("This is a meaningfull message."));
Sincerely yours,
Andrew Simontsev.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.