XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

((центр
На сайт валите, нефига =) xgm.ru/p/wc3/ifdebug-2
))

Ответ
 
ScorpioT1000
Работаем
offline
Опыт: отключен
IFDEBUG 2: Как жить без фаталов?
Думаю многие помнят небольшую, но очень полезную библиотечку от Doc которая помогала сохранять дебаг логи на хард по средствам прелоада и библиотечку от Скорпи, которая помогала контролировать в коде соблюдение различных условий.
Думаю, те кто пользовались, остались довольны, как и я.
Так вот, недавно Faion малость усовершенствовал первую, а скорпи присоединил вторую. Надеюсь, док и faion будут не против.
В результате получилось отличное средство от геморроя и немного от фаталов!
Инструкции:
//     Instructions:
//
//     Пишет информацию об условии в лог, если условие ВЫПОЛНИЛОСЬ:
// IFDEBUG( ARGUMENT ) 
//
//     Пишет информацию в лог, если условие НЕ ВЫПОЛНЕНО и УНИЧТОЖАЕТ весь текущий поток:
// ASSERT( ARGUMENT ) 
//
//     Пишет информацию об условии в лог, если условие ВЫПОЛНИЛОСЬ и выходит из функции со значением, указанным во втором аргументе:
// IFDEBUG( ARGUMENT, RET )
//
// Заметка: Если функция ничего не возвращает, но вы в любом случае хотите её остановить, используйте пробел, как: IFDEBUG(u == null, );
// Заметка: Это работает только в режиме отладки JNGP - "Debug Mode".
Code:
//     Instructions:
//
//     Writes log if the condition is satisfied:
// IFDEBUG( ARGUMENT ) 
//
//     Writes log if the condition is NOT satisfied and TERMINATES its thread:
// ASSERT( ARGUMENT ) 
//
//     Writes log if the condition is satisfied and returns value from the second argument:
// IFDEBUG( ARGUMENT, RET )
//
// Note: If the function returns nothing but you wanna stop it anyway, use the space like: IFDEBUG(u == null, );
// Note: It works only in JNGP "Debug Mode".

//     Configuration:
#define
{
    Debug = true
    private SavePath = NS_SNW_LOGS\\Logs
    private PerformanceSavePath = NS_SNW_LOGS\\PerformanceLogs
    private SaveOnHardDrive = true
    private HardDriveLetter = C
    private AutoSaveLog = true
    private LogSavePeriod = 5.0
}

// by Faion, 2012
// by DoctorGester (Doc), 2011

library DebugLog initializer DebugLogInit
{
    public bool EnableLogging = true
    private string array DebugLog
    private string array PerformanceDebugLog
    private int CurrentString = 0
    private int miliSeconds = 0
    private int Seconds = 0
    private int Minutes = 0
    private int Hours = 0
    private constant int StringLimit = 200
    
    private int pastVal = 0;
    private int PerformanceString = 0
    
    void PerformanceLogAdd()
    {
        if (!EnableLogging)
        {
            return
        }
        string min = I2S(Minutes)
        string sec = I2S(Seconds)
        string msec = I2S(miliSeconds)
        if (Minutes < 10)
        {
            min = "0" + min
        }
        if (Seconds < 10)
        {
            sec = "0" + sec
        }
        if (miliSeconds < 10)
        {
            msec = "0" + msec
        }
        location loc = Location(0,0);
        int hId = GetHandleId(loc);
        
        RemoveLocation(loc);
        loc = null;
        PerformanceDebugLog[PerformanceString] = PerformanceDebugLog[PerformanceString] + ("[" + I2S(Hours)+":" + min + ":" + sec + ":" + msec + "] " + I2S(hId-0x100000) + "\n")
        if (StringLength(PerformanceDebugLog[PerformanceString]) >= StringLimit)
        {
            PerformanceString++
        }
    }
    
    void PerformanceLogUpdate()
    {
        if (!EnableLogging)
        {
            return
        }
        PreloadGenClear()
        PreloadGenStart()
        int i = 0
        while (i <= PerformanceString)
        {
            Preload("\")\n" + PerformanceDebugLog[i] + "\n(\"")
            i++
        }
        #if SaveOnHardDrive
            PreloadGenEnd(`HardDriveLetter` + ":\\" + `PerformanceSavePath` + ".txt")
        #else
            PreloadGenEnd("\\" + `PerformanceSavePath` + ".txt")
        #endif
    }
    
    void LogAdd(string s)
    {
        if (!EnableLogging)
        {
            return
        }
        string min = I2S(Minutes)
        string sec = I2S(Seconds)
        string msec = I2S(miliSeconds)
        if (Minutes < 10)
        {
            min = "0" + min
        }
        if (Seconds < 10)
        {
            sec = "0" + sec
        }
        if (miliSeconds < 10)
        {
            msec = "0" + msec
        }
        DebugLog[CurrentString] = DebugLog[CurrentString] + ("[" + I2S(Hours)+":" + min + ":" + sec + ":" + msec + "] " + s + "\n")
        if (StringLength(DebugLog[CurrentString]) >= StringLimit)
        {
            CurrentString++
        }
    }
    
    void LogClear()
    {
        int i = 0
        while (i <= CurrentString)
        {
            DebugLog[i] = ""
            i++
        }
        CurrentString = 0
    }
    
    void LogUpdate()
    {
        if (!EnableLogging)
        {
            return
        }
        PreloadGenClear()
        PreloadGenStart()
        int i = 0
        while (i <= CurrentString)
        {
            Preload("\")\n" + DebugLog[i] + "\n(\"")
            i++
        }
        #if SaveOnHardDrive
            PreloadGenEnd(`HardDriveLetter` + ":\\" + `SavePath` + ".txt")
        #else
            PreloadGenEnd("\\" + `SavePath` + ".txt")
        #endif
    }
    
    private void DebugLogOnTimer()
    {
        miliSeconds++
        if (miliSeconds > 99)
        {
            miliSeconds = 0
            Seconds++
            if (Seconds > 59)
            {
                Seconds = 0
                Minutes++
                if (Minutes > 59)
                {
                    Minutes = 0
                    Hours++
                }
            }
        }
    }

    private void DebugLogInit()
    {
        #if AutoSaveLog
            TimerStart(CreateTimer(), LogSavePeriod, true, function LogUpdate)
            TimerStart(CreateTimer(), LogSavePeriod, true, function PerformanceLogUpdate)
        #endif
        TimerStart(CreateTimer(), 0.01, true, function DebugLogOnTimer)
        TimerStart(CreateTimer(), 0.10, true, function PerformanceLogAdd)
        LogAdd("By FaionBezarius. Last compilation: " + `DATE` + " " + `TIME`)
	#if Debug 
        	BJDebugMsg("By FaionBezarius. Last compilation: " + `DATE` + " " + `TIME`)
	#endif
    }
	
	
//   by ScorpioT1000, 2009
//   powered by AdicHelper(cJass.xgm.ru)

    #define private assert_color = "FF404040"

    nothing Ifdebug_debug_msg(string message, integer whichPlayer) {
		LogAdd("|c"+assert_color+"Debug: "+message+"|r")
    }
    
    #define private DMSGFUNC = Ifdebug_debug_msg
    
	#define IFDEBUGF(ARG,DEST_PLAYER) =  
	#define IFDEBUGFA(ARG,DEST_PLAYER) =  
	#define IFDEBUGR(ARG,WHATRET,DEST_PLAYER) =  
	
#if DEBUG == 1
    #setdef IFDEBUGF(ARG,DEST_PLAYER) = {
        if(ARG) {
            DMSGFUNC(`FUNCNAME` + ": " + `ARG`,DEST_PLAYER)
        }
    }
    #setdef IFDEBUGFA(ARG,DEST_PLAYER) = {
        if(ARG) {
        } else {
			DMSGFUNC(`FUNCNAME` + ": " + `ARG`,DEST_PLAYER)
			I2R(2/0)
		}
    }
    
    #setdef IFDEBUGR(ARG,WHATRET,DEST_PLAYER) = {
        if(ARG) {
            DMSGFUNC(`FUNCNAME` + ": " + `ARG`,DEST_PLAYER)
            return WHATRET
        }
    }
#endif
    
    //overloading
    #define {
	ASSERT(ARGUMENT) = IFDEBUGFA(ARGUMENT, -1)
        IFDEBUG(ARGUMENT) = IFDEBUGF(ARGUMENT, -1) // with condition to all players
        IFDEBUG(ARGUMENT,RET) = IFDEBUGR(ARGUMENT,RET, -1) // with condition and return to all players
        IFDEBUGP(ARGUMENT,DEST_PLAYER) = IFDEBUGF(A,DEST_PLAYER) // with condition to one player
        IFDEBUGP(ARGUMENT,RET,DEST_PLAYER) = IFDEBUGF(A,RET,DEST_PLAYER) // with condition and return to one players
    }
    
}
Примеры:
// функция остановится и в лог будет записано, что выполнено условие "u == null" в функции "foo"
function foo takes unit u returns nothing
    IFDEBUG(u == null, )
    KillUnit(u)
endfunction

// если не будет выполнено условие "x > 0", будет остановлена вся цепочка вызывавших ее функций и в логе будет запись об этой функции и условии
function xab takes integer a, integer b, integer c returns integer
    local integer x = a * b * c
    ASSERT(x > 0)
    return SquareRoot(x)
endfunction

// вернет false если хотябы один из юнитов равен null, запишет всё в лог
function bvc takes nothing returns boolean
    local unit u = GetTriggerUnit()
    local unit t = GetSpellTargetUnit()
    IFDEBUG(u == 0 or t == null, false)
    // ...
    return true
endfunction

Отредактировано ScorpioT1000, 14.06.2012 в 16:26.
Старый 14.06.2012, 16:09
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
// функция остановится и в лог будет записано, что выполнено условие "u == null" в функции "foo"
function foo takes unit u returns nothing
    IFDEBUG(u == null, )
    KillUnit(u)
endfunction
Строка IFDEBUG(u == null, ) правильная?
Что делать с темой Faion ?
Старый 14.06.2012, 16:14
ScorpioT1000
Работаем
offline
Опыт: отключен
Не знаю, у него спрашивайте =)
Да правильно, читай инструкции!
Старый 14.06.2012, 16:14
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
Думаю так как в логе все равно указывается автор,то тему Faion'a стоит хотя бы открепить
попутал=(
Старый 14.06.2012, 16:17
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Мою тему можно открепить, а эту пока прикрепить.
А чуть позже, я сделаю рефакторинг этой либы, приведу в нормальный вид и выложу.
Старый 14.06.2012, 18:14
vlad_C0M
Босс DarkSkyTeam
offline
Опыт: 10,459
Активность:
Faion, жду!
Старый 15.01.2013, 09:18
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Старый 15.01.2013, 10:17
vlad_C0M
Босс DarkSkyTeam
offline
Опыт: 10,459
Активность:
Faion, ооо , вижу вижу!

vlad_C0M добавил:
5 баллов!
Старый 15.01.2013, 10:58
ScorpioT1000
Работаем
offline
Опыт: отключен
Они немного разные. Суть этой либы остановить функцию в критической ситуации (если что-то не выполнилось), но избежать фатала. А у него я так понял просто отладка.
Старый 15.01.2013, 14:17
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
ScorpioT1000, прав, ибо я затачивал либу именно под отладку. Версия по ссылке заточено под то что бы отладить все, а потом попросту отключить либу, и все будет ок, не нужно будет вычищать отладки.
мб как нить добавлю еще уровени для логов.
Старый 15.01.2013, 17:49
ScorpioT1000
Работаем
offline
Опыт: отключен
Просто бывают случаи, которые даже самый пунктуальный кодер не проверит и вот тут то и будет фатал =)
Старый 15.01.2013, 17:55
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
ScorpioT1000, тру программист никогда не доверяет входным данным, да и в вц оч сложно добится фатала, а вот разрыв потока, десинк - легко.
Старый 16.01.2013, 00:42
ScorpioT1000
Работаем
offline
Опыт: отключен
Что значит никогда? Вопрос в том, на каком уровне функций сделана эта проверка и иногда составляет проблему узнать, а стоит ли проверять входные данные или они проверяются в функции ниже?
А если проверять в каждой функции то это приведет к проседанию фпс.
Старый 16.01.2013, 13:44
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
ScorpioT1000:
Что значит никогда?
Последний раз я ловил фатал когда пользовался гуями.
ScorpioT1000:
А если проверять в каждой функции то это приведет к проседанию фпс.
На этапе тестирования на это вообще пофиг. А после тестирования меняется флаг, и все отладочные функции выпиливаются препроцессором.
Старый 16.01.2013, 18:25
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 05:03.