Thread: Customized assert question...

  1. #1
    Registered User
    Join Date
    Nov 2005
    Posts
    673

    Customized assert question...

    Actually it really isnt that big of a deal, but i was just wondering if anyone happen to see a problem or insecurity with my assert setup. I don't like the regular assert.
    Code:
    //required for MessageBoxA() functions
    #include <windows.h>
    //required to use std::stringstream
    #include <sstream>
    
    //Check if program is debug build
    #ifndef NDEBUG
    
    //Assign the asert macro
    #ifdef assert
    #undef assert
    #endif
    
    #if defined(BOX)
    #define assert Wassert
    #elif defined(CONSOLE)
    #define assert Cassert
    #else
    #define assert assert
    #endif
    
    #if defined(BOX)
    #define createBox \
    struct create \
        {\
    create(const int& line, const char* file, const char* message)\
    {\
    std::stringstream ss;\
    const char* title = "Assertion Error!!!";\
    ss << "!!!Assertion Error!!!\nFile: " << file << "\nLine: " << line << "\n\n" << message;\
    MessageBoxA(NULL,ss.str().c_str(),title, 0);\
    };\
        } myboxmaker = create
    #endif
    
    //
    #ifdef CONSOLE
    #define Cassert \
        if ( false ) {} else struct LocalAssert { \
        int mLine; \
        LocalAssert(int line=__LINE__) : mLine(line) {} \
        LocalAssert(bool isOK, char const *message="", bool quit = false) { \
        if ( !isOK ) { \
        (void)printf("ERROR!! Assert failed on " \
        "line %d in file\n-->%s\n%s\n", \
        LocalAssert().mLine, __FILE__, message); \
        if (quit) \
           abort();\
        else\
        __asm { int 3 } \
        } \
    }\
        }myAsserter = LocalAssert
    #endif
    
    //checks if Wassert is to be used
    #ifdef BOX
    #define Wassert \
        if ( false ) {} else struct LocalAssert { \
        int mLine; \
        LocalAssert(int line=__LINE__) : mLine(line) {} \
        LocalAssert(bool isOK, char const *message="", bool quit = false) { \
        if ( !isOK ) { \
        createBox(LocalAssert().mLine, __FILE__, message);\
        if (quit) \
        abort();\
        else\
        __asm { int 3 } \
        } \
    }\
        }myAsserter = LocalAssert
    #endif
    
    #ifndef BOX
    #ifndef CONSOLE
    #define assert \
        if ( true ) {} else struct NoAssert { \
        NoAssert(bool isOK, char const *message="", bool quit = false) {} \
        } myAsserter = NoAssert
    #endif
    #endif
    
    #endif
    Well thanks, and maybe someone else will be able to use this as well.

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I suggest you make them into functions instead of macros. It will be much easier to spot and fix errors if you do.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    I can really help Raigne. I get an headache trying to read macro definitions. But one thing I did notice however is that you probably could #ifdef that windows.h include to cut on compilation times
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    My personal opinion would be that you define a SHORT macro that does the actual assertion (if (condition) do_assert(line, file, #cond), and then call a function that does the actual "show message and stop".

    This is something I just hacked up right now:
    Code:
    // myassert.h
    void domyassert(const char *msg, int line, const char *file);
    
    #define myassert(x) do { if (!(x)) domyassert(#x, __FILE__, __LINE__); } while(0)
    
    
    // myassert.c:
    #include <stdio.h>
    
    void domyassert(const char *msg, const char *file, int line)
    {
    	fprintf(stderr, "Assert failed: %s at %s:%d\n", msg, file, line);
    	__asm int 3;
    }
    You may of course want to have two different versions of "domyassert", depending on whether you do "Windows" or "Console" mode programs. If you don't want to have myassert.c as part of your project, you are probably going to use an #if solution in the header file and implement two different domyassert functions.

    The problem with your solution is that it creates a new function every single time you add an assert() in the code, which means that you end up with a LOT of extra code. The above code adds about 15 bytes per assert . Your code most likely adds a whole

    I take it your "if (false) ; else" is a different way to tackle the "do { ... } while (0)" standard way to ensure that a complex macro can be used as a simple C statement. Why not use "do ... while (0)" like everyone else?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    hmm, ill clean it all up with the suggestions mentioned and repost.

  6. #6
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    I came up with this for my assert. It does look alot better.
    Code:
    #pragma once
    
    //Check if program is debug build
    #ifndef NDEBUG
    
    void __assert_win32_(const char* message, const char* file, const int& line); 
    void __assert_console_(const char* message, const char* file, const int& line);
    
    #if defined(WIN32_ASSERT)
    #define assert(x) do { if (!x) { __assert_win32_(#x, __FILE__, __LINE__); } } while(0);
    #elif defined(CONSOLE_ASSERT)
    #define assert(x) do { if (!x) { __assert_console_(#x, __FILE__, __LINE__); } } while(0);
    #endif
    
    #endif
    and the implementation of the functions is
    Code:
    #include "myassert.h"
    
    void __assert_win32_(const char* message, const char* file, const int& line)
    {
    	std::stringstream ss;
    	ss << "Assertion Error: \nFile: " << file << "\nLine: " << line << "\n\nVariable: " << message;
    	MessageBoxA(NULL, ss.str().c_str(), "!!!ASSERT ERROR!!!", NULL);
    	__asm { int 3 }
    }
    
    void __assert_console_(const char* message, const char* file, const int& line)
    {
    	printf("Error Variable: &#37;s\nFile: %s\nLine: %d",message, file, line);
    	__asm { int 3 }
    }
    Hope this will help someone.

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Why the #pragma once? And why the double underscores? And how important is the assembly part?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The assembly part fires up the debugger, if any is installed. A better way would be to call Win32's DebugBreak().

    The double underscores are unacceptable, though.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I believe the #pragma part is a MS-ism to avoid include guards - I prefer the traditional approach of using include-guards, but that's just me.

    As CornedBee says, the __asm int 3 is a "breakpoint trap", so if you have a debugger on the machine, you can fall straight into the debugger.

    I agree, the double underscores are reserved for "compiler implementation", and just to make sure you don't clash, you should use your own variant to ensure your names are unique enough.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    I thought it was single underscore prefix for the compiler, and the assembly is to actually trigger a breakpoint, but unlike the abort() function which does the same thing it does not terminate the program at the assert call. if that makes any sense.

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Everything starting with an underscore is for the compiler. A single underscore is reserved for global identifiers, meaning you may give locals, class members and elements within namespaces such names, but not top-level globals, constants of top-level enums, or macros. And I'd advise against the allowed cases, too.
    A double underscore or an underscore followed by an upper-case letter is completely reserved. The compiler may define macros, extension keywords and whatever else it wants with such names, thus making them unsafe to use for you in any context.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Debugging question
    By o_0 in forum C Programming
    Replies: 9
    Last Post: 10-10-2004, 05:51 PM
  2. Question about pointers #2
    By maxhavoc in forum C++ Programming
    Replies: 28
    Last Post: 06-21-2004, 12:52 PM
  3. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 09:47 PM
  4. Question about linked lists.
    By cheeisme123 in forum C++ Programming
    Replies: 6
    Last Post: 02-25-2003, 01:36 PM
  5. Question, question!
    By oskilian in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 12-24-2001, 01:47 AM