• pudin9 (unregistered)

    We don't even need submissions, I could keep reading about your fails forever :D

  • (nodebb)

    So, it's important to note that there's no way for new to fail without an exception being thrown.

    That's not universally true. If the CRetailCustomer class defines a class-specific operator new, it doesn't have to throw, so ...

    But let's imagine, through some miracle, pRetail somehow was null.

    It wouldn't be miraculous, but pratitudinous.

  • (nodebb)

    SO many things wrong with this article..

    1. Macros should (generally) NOT be in C++ programs at all, instead the use of templates is appropriate.
    2. "new" CAN be configured to NOT throwin many different ways. See the following for just one: https://www.cplusplus.com/reference/new/nothrow/
    3. calling a non-virtual member function of a class via a pointer declared of that type, but currently set to null will NOT throw an exception.
  • Prime Mover (unregistered)

    If you're cutting a branch off a tree, if you're sitting on that branch, make sure you're sitting on the tree side of the saw.

  • Anonymous') OR 1=1; DROP TABLE wtf; -- (unregistered) in reply to TheCPUWizard

    calling a non-virtual member function of a class via a pointer declared of that type, but currently set to null will NOT throw an exception.

    That's Undefined Behavior, so it could very well throw an exception. Most likely it'll segfault, but if the method's logic resulted in throwing an exception without accessing any of the fields or other methods of this, that would result in an exception.

    Another more subtle problem with this macro is if it's used in call sites like this:

    if (foo)
        if (bar)
            CHECK_CONDITION(condition, FailureOp);
        else
            do_something_else();
    

    After macro expansion, this becomes:

    if (foo)
        if (bar)
            if (!(condition)) {
                FailureOp;
            }; // <-- semicolon ends the if (bar)
    else
        do_something_else();
    

    The else now silently matches with the wrong if, without any compiler warnings or errors!

    Now this is certainly bad code (nested ifs without braces) and a perfect example of why macros are evil. But it's why whenever you have if statements inside macros, you should differently, like this:

    // 1:
    #define CHECK_CONDITION(condition, FailureOp) if (condition) /*nop*/; else { FailureOp; }
    // Or, 2:
    #define CHECK_CONDITION(condition, FailureOp) do { if (!(condition)) { FailureOp; } } while (0)
    
  • (nodebb) in reply to TheCPUWizard

    Macros should (generally) NOT be in C++ programs at all, instead the use of templates is appropriate.

    Doesn't work when the expanded macro is doing something with the control flow (such as in the article). Templates are all very well (in their saner forms at least) but there are things they can't do because they're structured like functions (for good reason).

  • ichbinkeinroboter (unregistered)

    https://www.artofmanliness.com/articles/toolmanship-how-to-use-a-handsaw/

  • The incredible Holk (unregistered)

    #define false true

  • (nodebb) in reply to Anonymous') OR 1=1; DROP TABLE wtf; --

    In C,

    #define CHECK_CONDITION(condition, FailureOp) do { if (!(condition)) { FailureOp; } } while (0)
    

    is usually preferred because it allows CONDITION_CHECK to behave syntactically like a function call. However, using it in this case is likely to cause hard to spot errors e.g.

    while (someCondition)
    {
        CONDITION_CHECK(some_other_condition, break);
        // do stuff
    }
    
  • (nodebb) in reply to Anonymous') OR 1=1; DROP TABLE wtf; --

    @anon- Yes, it is UB.... But every compiler I have encountered will happy accept it... The value of 'this" is not used unless there is a need to reference a member or the vtable

    @dkf - Did you ever see the implementation of TicTacToe as nothing more than set of templates all with compile time decisions. The game was constrained that when there were multiple equivilantt moves, the "upper left" would always be chosed - this made the game deterministic, and though there was lots of "coded logic" in the source, the final optimized code was noting more thn a series of "cout <<" statements! One can argue if this is a sane use... but it is no doubt an amazing one...

  • Wizofaus (unregistered)

    Just me or does that dynamic_cast statement look like it shouldn't compile?

  • Officer Johnny Holzkopf (unregistered) in reply to TheCPUWizard

    Not intending to insult the humble author, but... is "pre-compiler" a new way of spelling the word "preprocessor"? Or does the name change depending on usage with C, C++, or C# code? And what if the C preprocessor macros are used for non-C* purposes?

  • löchleindeluxe (unregistered)

    So… basically this looks like somebody read an article on assert, didn't understand it, wrote this macro and told somebody else what they thought assert was, who then wrote this code.

  • (nodebb) in reply to TheCPUWizard

    "calling a non-virtual member function of a class via a pointer declared of that type, but currently set to null will NOT throw an exception" - what a language! It might do nothing obviously bad, I suppose, but what it won’t do is whatever the programmer expected it to do.

Leave a comment on “Dangerous Tools for Dangerous Users”

Log In or post as a guest

Replying to comment #:

« Return to Article