PrintDec/PrintHex/PrintString в C++

Тема в разделе "WASM.ZEN", создана пользователем cresta, 9 сен 2005.

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Есть самодельная тулза для c++, которая выводит некую отладочную информацию о состоянии регистров и значениях переменных, наподобие масмовских PrintDec/PrintHex/PrintString из VKDebug.

    Значения для вывода приходится передавать как в процедуру (собственно процедура и выводит), и передавать три параметра

    int Debug(LPSTR ValueName, int value, int Type);

    Передавать три параметра неудобно, кроме того приходится постоянно заниматься преобразованием типов передаваемых переменных в LPSTR и int.

    Может как-нибудь define пристегнуть к этому делу?

    Можно ли в этом говяжьем языке цэ придумать что-нибудь, чтобы можно было писать просто: PrintDec MyVar, без указания типа переменной и строки, содержащей её имя для отображения.
     
  2. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Можно перегрузить несколькими функциями:
    Код (Text):
    1.  
    2. #define DBG_VAL(x) Debug(## x,x)
    3. int Debug(LPCSTR ValName,LPSTR StrValue);
    4. int Debug(LPCSTR ValName,int IntValue);
    5. int Debug(LPCSTR ValName,double DoubleValue);
    6. ...
    7.  
    8. int var = 98;
    9. DBG_VAL(var);




    За корректность кода ручаться не могу, но общий смысл ясен: за счёт перегрузки функций избавляемся от параметра типа переменной, за счёт макроса — от имени переменной.
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Идея понятна, а как реализовать - не понял :dntknw:



    Сама функция (на всякий случай):


    Код (Text):
    1. extern int Debug(LPSTR ValueName, int value, int Type){
    2.     char*        fmt1=NULL;
    3.     char         buffer1[512];
    4.     char         buffer2[512];
    5.     short        crlf=0x0a0d;
    6.     LPSTR        StrValue=NULL;
    7.  
    8.         if (!FindDbg()) return 0;
    9.    
    10.         SendMessage (hDbgEdit, EM_SETSEL, -1, -1);
    11.         switch (Type){
    12.             case 0:         //----------- Print Decimal Value (Type==0) ------------
    13.                 fmt1=" = %li";
    14.                 break;
    15.        
    16.             case 1:         //----------- Print Hexadecimal Value (Type==1) --------
    17.                 fmt1=" = 0x%08lX";
    18.                 break;
    19.  
    20.             case 2:         //----------- Print String Value (Type==2) -------------
    21.                 if (!IsBadReadPtr(ValueName,1)){
    22.                     strcpy(buffer2,ValueName);
    23.                     strcat(buffer2," = ");
    24.                     StrValue=(LPSTR)VirtualAlloc(NULL,65536,MEM_COMMIT,PAGE_READWRITE);
    25.                     strcpy(StrValue,(LPSTR)value);
    26.                     strcat(buffer2,StrValue);
    27.                     }
    28.                 else {
    29.                     strcpy(buffer2,"Bad String Pointer!");
    30.                     }
    31.                 strcat(buffer2,(const char*)&crlf);
    32.                 break;
    33.             }
    34.    
    35.     if (Type !=2){
    36.         strcpy(buffer1, ValueName);
    37.         strcat(buffer1, fmt1);
    38.         wsprintf(buffer2,buffer1,value);
    39.         strcat(buffer2,(const char*)&crlf);
    40.         }
    41.     SendMessage (hDbgEdit, EM_REPLACESEL, 0,(LPARAM)buffer2);
    42.     if (NULL!=StrValue) VirtualFree(StrValue,65536,MEM_DECOMMIT);
    43.     return 0;
    44. }




    Тип вывода dec/hex/string - это понятно, а как с именем переменной и её значением - нет.


    Код (Text):
    1.     #define PrintDec    (???) Debug(???, ???, 0);
    2.     #define PrintHex    (???) Debug(???, ???, 1);
    3.     #define PrintString (???) Debug(???, ???, 2);




    Если просто сделать PrintDec(x), то ошибка: undefined symbol x, если описать её тип, то только один тип можно передавать. И как извлечь само имя переменной, кроме её значения?
     
  4. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Способов много. Вот например:
    Код (Text):
    1.  
    2. void Debug(LPCSTR ValueName, int value, int Type)
    3. {
    4.     printf("\tvariable: %s, type: %d, value: %X\n",ValueName,value,Type);
    5. }
    6.  
    7. #define DBG_VAL(x) Debug(# x,x)
    8. void Debug(LPCSTR ValName,LPSTR StrValue)
    9. {
    10.     Debug(ValName,(int)StrValue,2);
    11. }
    12. void Debug(LPCSTR ValName,int IntValue)
    13. {
    14.     Debug(ValName,IntValue,0);
    15. }
    16. //void Debug(LPCSTR ValName,double DoubleValue);
    17.  
    18. int main(int,char*)
    19. {
    20.     char* sz = "hello, dword";
    21.     int n = strlen(sz);
    22.    
    23.     DBG_VAL(sz);
    24.     DBG_VAL(n);
    25.    
    26.     printf(sz);
    27.     return 0;
    28. }


    Хотя, идея вывода отладочный сообщений в диалог всегда претила мне и VKDebug не использовал.



    И для ассемблеров (масм/фасм), и для с++ написал такое:
    Код (Text):
    1. DebugFmt("calling X(): arg1(%d), arg2(%s)",arg1,arg2);


    У меня отладочные сообщения выводятся в OutputDebugString и/или лог-файл, иногда с автоматическим добавлением имени файла и номера строки.



    /offtop

    Жаль, RadASM не парсит сообщения компилятора, если ExitCode последнего равен 0 (success), а #pragma warning нет ни в масме, ни в фасме.
     
  5. SDragon

    SDragon New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2005
    Сообщения:
    133
    Адрес:
    Siberia


    Здесь выход за границы буфера, если размер строки больше 65536. В этом случае лучше написать свою функцию, копирующую строки до 65536-го символа.

    [​IMG] _1868859233__Debug.rar
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    SDragon

    strncpy :)
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent

    Всё, сделал, спасибо.

    Саму функцию оставил без изменения и дальше так:



    int x;

    LPSTR sz;



    #define DBG_DEC(x) Debug(# x,x,0)

    #define DBG_HEX(x) Debug(# x,x,1)

    #define DBG_STR(sz) Debug(# sz,(int)sz,2)

    ...

    ...

    ...

    DBG_DEC(my_int);

    DBG_HEX(my_short);

    DBG_STR(my_string);

    _asm{int 3};



    Всё выводит, как имя переменной, так и её значение



    SDragon

    Эта утилитка вряд ля кому ещё понадобится, а сам я помню про ограничение длины 65536 :)
     
  8. SDragon

    SDragon New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2005
    Сообщения:
    133
    Адрес:
    Siberia


    Ой, точно... Ну и балбес я :).