View Single Post
addons_zz
Veteran Member
Join Date: Aug 2015
Location: Dreams, zz
Old 01-13-2016 , 18:41   Re: [TUT] How to use a 100% efficient debug system, which do not overload your final
Reply With Quote #2

Notes | go to top
  1. Every time you break lines on the preprocessor functions 'DEBUG_LOGGER' or any other, you must end its like using a inverted bar '\', without any spaces after it. Example:
    Code:
        DEBUG_LOGGER( 3,  "^nI am doing debug, the current time is: \             %d:%d:%d^n", \             hour, minute, second )
  2. It is a convention to write the preprocessor function and variables using upper case letter, to differ from the rest of the code, as they are not ordinary code. They are not ordinary code, because they are expanded by the preprocessor, which happens before the compiler, generate your final code. Example:
    Spoiler

  3. If you have enabled the semicolon using '#pragma semicolon 1', you cannot put a semicolon on the preprocessor macro 'DEBUG_LOGGER(...)', because they already got one at its declaration. Example:
    Code:
    #if IS_DEBUG_ENABLED > 0 #define DEBUG_LOGGER(%1) debugMesssageLogger( %1 ); ... some code #pragma semicolon 1 ... some code /*  * Called just after server activation.  */ public plugin_init() {     DEBUG_LOGGER( 1,  "^n^nI am ENTERING on plugin_init()" )     register_plugin( "Cool Plugin", "1.0", "Addons zz" );     register_concmd( "amx_next", "do_debug" );     do_debug();     DEBUG_LOGGER( 2,  "I am LEAVING on plugin_init()^n" ) }
  4. When you run the plugin, its executes/run/works/do things, you need to know how it is doings things, what function is called before what, why it is being called, and why it is not being called. To do that, to accomplish that, to put a lot of server_prints, and put more server_prints, until you get to know all information that do you need to understand what the plugin is doing, when you are using it, this is called debug. See [TUT] How to use an efficient debug system, which do not overload your final code, but it use, what I could call 'advanced concepts'. However, on the thread beginning and contents, you can find various others tutorials and links to understand things.

    You cannot forget also to read the Amx Mod X documentation, to get to know what your functions do, and why they do. And the tutorials to know more about how things get done. But if some documentation is missing or you do not understand, search, search, search, search, the forums, until you find some thing as example or a plugin which uses that function where you maybe can know what is does when you see what plugin code running. But if all that isn't enough, open the AMX Mod X Source Code and start learning by its functions implementations what does they do. And even better, contribute to the community, once you know it, to do a pull request to add the missing or bad documentation to the official AMX Mod X Source Code. Moreover, much more better is if you find bugs, fix them instead of just complaining or opening a bug/issue report.

    Also, when you get a plugin and modifies it, do not remove thing on the fly unless you are sure they are useless. And to know if they are useless, to debug the code, to read the Amx Mod X documentation, to read the tutorials and search, search, search, search.

  5. Programming in movies vs real life

    http://imgur.com/Kgz562w


  6. So Adele, what do you think about programmer?



Frequently Asked Questions - FAQ | go to top
  1. Code have no bug man! Successfully compiled.
    • Debug is not just to find bugs, it is also to understand what the plugin is doing, and how it is doing.
    • And there two bug types.

  2. If I want to put this here, is it a problem?
    Code:
    public client_disconnect(id) {     DEBUG_LOGGER( 1,  "^n^nI am ENTERING on plugin_init()" )         if((id == g_iChallenged) || (id == g_iChallenger))     {         g_bInChallenge = false;         g_bProtect = false;     } }
    Yes, because that function is not plugin_init(), it is: client_disconnect(id). Example:
    Code:
    public client_disconnect(id) {     DEBUG_LOGGER( 1, "^n^nI am ENTERING on client_disconnect(id)" )         if((id == g_iChallenged) || (id == g_iChallenger))     {         g_bInChallenge = false;         g_bProtect = false;     } }
    And actually it is now much more better. You can also show more information. Example:
    Code:
    public client_disconnect(id) {     DEBUG_LOGGER( 1, "^n^nI am ENTERING on client_disconnect(id), the client_id is %d, ^n\             the challenged id is %d, the chalanger id is %d, the variable g_bInChallenge is %d, ^n\             the variable g_bProtect is %d^n", \             id, g_iChallenged, g_iChallenger, g_bInChallenge, g_bProtect )                 if( ( id == g_iChallenged )           || (id == g_iChallenger) )     {         g_bInChallenge = false;         g_bProtect = false;     } }

  3. Only for public?
    Code:
    stock vec_null( Float:vec[3] ) {     DEBUG_LOGGER( 2,  "I am LEAVING on vec_null()^n" )         if( !vec[0]         && !vec[1]         && !vec[2] )     {         return 1;     }         return 0; }
    This is not good because you are not LEAVING, you are ENTERING, put is at the function end before the return statement. Then it is fine, because you are actually LEAVING. Example:
    Code:
    stock vec_null( Float:vec[3] ) {     DEBUG_LOGGER( 1,  "I am ENTERING on vec_null()^n" )         if( !vec[0]         && !vec[1]         && !vec[2] )     {         DEBUG_LOGGER( 2,  "I am LEAVING on vec_null() returning 1^n" )         return 1;     }         DEBUG_LOGGER( 2,  "I am LEAVING on vec_null() returning 0^n" )     return 0; }

C/C++ Language Implementation | go to top

Introduction links:
  1. Variadic Macros
  2. When to use extern in C++
  3. C Storage Classes
  4. C Programming/Preprocessor
  5. Yale University - C Macros
  6. what is the function of "extern" in C++
  7. Undefining and Redefining Macros
  8. Overloading Macro on Number of Arguments
  9. References & the Copy-Constructor
  10. Macro Align on Linux Kernel

Put this on your header file and define and initialize the variable 'g_debug_level' on somewhere else. Just inicialize the variable 'g_debug_level' at one of them.

The header file 'debug_functions.h':
Code:
#define IS_DEBUG_ENABLED 1 #if IS_DEBUG_ENABLED > 0 /**  * ( 0 ) 0 disabled all debug.  * ( 1 ) 1 displays basic debug messages.  * ( 10 ) 2 displays PAWN specific stuff.  * ( 11 ) 3 displays all debug levels.  */ extern int g_debug_level; /**  * This print to the standard output, the debug information passed accordingly to the global  * constant g_debug_level.  *  * @param mode the debug mode level, see the directive 'g_debug_level' for the levels.  * @param message[] the text formatting rules to display. Example: "Hi today is %s-%s"  * @param any the variable number of formatting parameters. Example: day_name, the_time  */ #define DEBUG_LOGGER(mode,...) if( mode & g_debug_level ) \ { \     fprintf( stderr, __VA_ARGS__ ); \ } #else     #define DEBUG_LOGGER(...) //     #endif
The C/C++ file which initializes 'g_debug_level':
Code:
#include "debug_functions.h" #if IS_DEBUG_ENABLED > 0     int g_debug_level = 15; #endif int main(int argc, char *argv[]) {      DEBUG_LOGGER( 1, "Doing debug" ); }
Any C/C++ file which just use the variable 'g_debug_level', examples:
  • Example 1:
    Code:
    #include "debug_functions.h" int main(int argc, char *argv[]) {      DEBUG_LOGGER( 1, "Doing debug" ); }
  • Example 2:
    Code:
    #include "debug_functions.h" int main(int argc, char *argv[]) { #if IS_DEBUG_ENABLED > 1     if( g_debug_level & 8 )     {         static int counter = 0;         DEBUG_LOGGER( 1, " ( main ) current call count: %d", counter++ );     } #endif }
__________________
Plugin: Sublime Text - ITE , Galileo
Multi-Mod: Manager / Plugin / Server

Support me on Patreon, Ko-fi, Liberapay or Open Collective

Last edited by addons_zz; 05-27-2017 at 10:45. Reason: adjusted the source code formatting
addons_zz is offline