The Daily WTF: Curious Perversions in Information Technology
Welcome to TDWTF Forums Sign in | Join | Help
in Search

the null check that follows is not redundant!

Last post 03-26-2008 9:45 AM by Spectre. 15 replies.
Page 1 of 1 (16 items)
Sort Posts: Previous Next
  • 03-20-2008 5:44 PM

    • arty
    • Top 500 Contributor
    • Joined on 01-09-2007
    • Posts 105

    the null check that follows is not redundant!

                    // The constructor actually sets up the renderer, so the null check
                    // that follows is not redundant!
                    TheUI = new AnonymizedClassName(newDatabase);
                   
                    if (null != TheUI)
                    {
     

    However, the 'new' operator is defined to return the newly constructed object or throw OutOfMemoryException if it fails. 

    I shudder to think what awaits beyond the next corner?  A race condition?  A misplaced assumption?

     

    [edit] 

    Here's the exciting conclusion

            static public AnonymizedClassName TheUI
            {
                get
                {
                    return sTheUI;
                }
                private set
                {
                    AnonymizedClassName toSet = value;
                    if (toSet != null && toSet.Database == null)
                        toSet = null;

                    if (sTheUI != toSet)
                    {
                        if (sTheUI == null)
                            TimerManager.InitializeTimer();
                        if (toSet == null)
                            TimerManager.KillTimer();

                        AnonymizedClassName oldTheUI = sTheUI;
                        sTheUI = toSet;
                        if (TheUIChanged != null)
                            TheUIChanged(oldTheUI, toSet);
                    }
                }
            }
     

    Filed under:
  • 03-21-2008 1:03 AM In reply to

    Re: the null check that follows is not redundant!

    arty:

                    // The constructor actually sets up the renderer, so the null check
                    // that follows is not redundant!
                    TheUI = new AnonymizedClassName(newDatabase);
                   
                    if (null != TheUI)
                    {
     

    However, the 'new' operator is defined to return the newly constructed object or throw OutOfMemoryException if it fails. 

    I shudder to think what awaits beyond the next corner?  A race condition?  A misplaced assumption?

     

    I once did something bad.

     

    It was back in the early days of c++ and we were all still using cfront.  Exceptions were a rarity back in those days.

     

     

    I had an object that did some initialisation in the constructor.  Yeh, I know that's bad now, but it was the first time I'd ever worked with the language.

     

     

     

    If the initialisation failed in the constructor, I did this:

        if (status < 0)
        {

            delete this

            this = NULL;

            return;
        }

    So you really did need to write

        cFoo *pFoo = new cFoo;

        if (pFoo == NULL)

        {

            // error handling

        }

    Yes.  I know. 

     

    I'm going to hell, aren't I?

  • 03-21-2008 9:24 AM In reply to

    Re: the null check that follows is not redundant!

    DaveK:
    I had an object that did some initialisation in the constructor.  Yeh, I know that's bad now

    Wait, when is this bad since?

    And, regarding your snippet — could this really work? Even if Cfront allowed to change this (bleccchhh), wouldn't it only affect the implicit parameter passed to the constructor?
    ╩юфют√ь ёЄЁрэшЎрь яюЁр эр яхэёш■.

    Visit #TDWTF @ SlashNET - the semi-official WTF IRC channel.
  • 03-21-2008 12:08 PM In reply to

    Re: the null check that follows is not redundant!

    Spectre:
    DaveK:
    I had an object that did some initialisation in the constructor.  Yeh, I know that's bad now

    Wait, when is this bad since?

    Well, it's specifically initialisation operations of the kind that might fail, or might have dependencies on other parts of the application or system being up and running, and it's less of an issue nowadays where exceptions are implemented everywhere, but I was taught back then that as a style issue it's good to only do simple member initialisations in your c-tors and to have an "int Initialise()" member function that does the actual run-time initialisation and can return an error status.  Frex, if your object has to open and read a file, you pass in the filename to the c-tor, which stashes it away, but you don't try fopening the file until Initialise() time.   Like all style issues, it's not an absolute rule, but it mattered more when you couldn't just throw.  These days, I'd suppose it's less useful, but it's still a reasonable pattern to use in an application where you might have a lot of statically-constructed objects that might be c-tored in a fairly arbitrary order by the runtime startup.  E.g., I've heard of bugs where people use stdio in a c-tor and it all works fine whent they're new'ing stuff, but when they make an object static it can be c-tored at startup before the stdio library initialisation has run and the stdio calls fail mysteriously.

    Spectre:
    And, regarding your snippet — could this really work? Even if Cfront allowed to change this (bleccchhh), wouldn't it only affect the implicit parameter passed to the constructor?
     

    It did work, although probably only because the c-tor got inlined whereever it was invoked, but I tested it by forcing the failure and the code that had called new did indeed get a null pointer return.

    I never tried to understand how or why it worked, because Cfront-generated code is among some of the most nightmarish, monstrous, illegible bizarre gibberish machine generated spew that I have ever set eyes on in my life.  Hundred line statements composed of an impenetrable sequence of nested brackets and comma-separated expressions and synthetic symbol names that won't even fit on your screen in one go.  Sometimes my eyes still bleed at the thought!

  • 03-21-2008 12:44 PM In reply to

    Re: the null check that follows is not redundant!

    Spectre:
    And, regarding your snippet — could this really work? Even if Cfront allowed to change this (bleccchhh), wouldn't it only affect the implicit parameter passed to the constructor?

    Did you mean the original snipplet? I see "Name{get{}set{}" there, so I guess it's C hash, not any incarnation of c++... then "new" will always be not null.

    Strange thing is that they blame constructor, but the problem is with property setter...

    Filed under: ,
  • 03-21-2008 2:51 PM In reply to

    Re: the null check that follows is not redundant!

    viraptor:

    Spectre:
    And, regarding your snippet — could this really work? Even if Cfront allowed to change this (bleccchhh), wouldn't it only affect the implicit parameter passed to the constructor?

    Did you mean the original snipplet?

    Nahh, he meant mine in the first reply. 

    Filed under: , ,
  • 03-24-2008 7:51 PM In reply to

    Re: the null check that follows is not redundant!

    Spectre:
    And, regarding your snippet — could this really work? Even if Cfront allowed to change this (bleccchhh), wouldn't it only affect the implicit parameter passed to the constructor?

    Where do you think that implicit parameter is created?

    In the constructor. As a local variable. So you can do whatever you want to it during the constructor; the constructor owns it. At the end of the constructor, this local variable is tossed out as the return value, which works because it's a handle to a global memory block.

    Which is... you guessed it... the real WTF. When you really dig under the covers of C++ and see how enterprisey it is, you start to understand why the ANSI C folks like myself were hesitant to adopt it - some of the things it does are simply insane.

    But they work, so you learn to shrug your shoulders and work in it anyway. Especially when it will happily compile ANSI C without complaining. ;)

  • 03-24-2008 8:34 PM In reply to

    Re: the null check that follows is not redundant!

    CDarklock:

    Where do you think that implicit parameter is created?

    In the constructor. As a local variable. So you can do whatever you want to it during the constructor; the constructor owns it. At the end of the constructor, this local variable is tossed out as the return value, which works because it's a handle to a global memory block.

    Wait wait wait wait wait. It cannot be this way. The constructor isn't the one to decide where the object is stored. For example:
    class A { /* stuff... */ };
    
    void F
    {
      A a;
    }
    
    Here, the position of the a object is predetermined, though it still needs to be passed to the constructor, so it will know where to construct the object. And if the object is dynamically allocated, operator new decides where to put it, not the constructor. And what's so enterprisey about C++?
    ╩юфют√ь ёЄЁрэшЎрь яюЁр эр яхэёш■.

    Visit #TDWTF @ SlashNET - the semi-official WTF IRC channel.
  • 03-24-2008 11:53 PM In reply to

    Re: the null check that follows is not redundant!

     Looks like a race condition for me.

    The good doctor is here to help. I promise this time I will not screw up the operation.
  • 03-25-2008 5:16 PM In reply to

    Re: the null check that follows is not redundant!

    Spectre:

    Wait wait wait wait wait. It cannot be this way. The constructor isn't the one to decide where the object is stored.

    You're not understanding me. The constructor OWNS the one and only reference to the object between memory allocation (which is WHEN the object gets stored) and accessibility to other code. So if you "delete this" during the constructor, that's perfectly valid, because the constructor just has a handle to a memory block and - as you imply - does not know it's already allocated and can't be legitimately deleted. The constructor can't tell the difference between "new" and value-type declaration.

    The last time I read anything official about this, the behavior if your class A said "delete this" in the constructor was still undefined. But I haven't been particularly amused by language-lawyering for years.

    And what's so enterprisey about C++?

    See above.

  • 03-25-2008 5:40 PM In reply to

    Re: the null check that follows is not redundant!

    CDarklock:

    You're not understanding me. The constructor OWNS the one and only reference to the object between memory allocation (which is WHEN the object gets stored) and accessibility to other code. So if you "delete this" during the constructor, that's perfectly valid, because the constructor just has a handle to a memory block and - as you imply - does not know it's already allocated and can't be legitimately deleted. The constructor can't tell the difference between "new" and value-type declaration.

    Well, yes. For a brief time, the constructor has the only pointer to the object. But it doesn't create it, it just uses it. So, when translating to C, the prototype of the constructor would be:
    void A_A (A * this, /* other arguments */);
    
    If you change this inside the constructor, the change is lost and has no further effect.
    ╩юфют√ь ёЄЁрэшЎрь яюЁр эр яхэёш■.

    Visit #TDWTF @ SlashNET - the semi-official WTF IRC channel.
  • 03-25-2008 6:01 PM In reply to

    Re: the null check that follows is not redundant!

    Spectre:

    Well, yes. For a brief time, the constructor has the only pointer to the object. But it doesn't create it, it just uses it. So, when translating to C, the prototype of the constructor would be

    ...wrong.

     A* A_A (A *this, /* other arguments */) { return a; }

    Once upon a time, C++ was simulated in ANSI C using macros.

  • 03-25-2008 7:18 PM In reply to

    • PJH
    • Top 25 Contributor
    • Joined on 02-14-2007
    • Posts 624

    Re: the null check that follows is not redundant!

    CDarklock:
    Spectre:
    Wait wait wait wait wait. It cannot be this way. The constructor isn't the one to decide where the object is stored. For example:
    class A { /* stuff... */ };
    
    void F
    {
      A a;
    }
    You're not understanding me. The constructor OWNS the one and only reference to the object between memory allocation (which is WHEN the object gets stored) and accessibility to other code. So if you "delete this" during the constructor, that's perfectly valid[...]
    In the snippet given, it is not legal in C++ for you to call
    delete this;
    anywhere (let alone the constructor) because the object is on the stack. (Nor would it be legal if created by new[ ], placement new, if it were a global, or a member of another object)
    This is not a problem that requires infinite wisdom, Benj. This is a problem that requires enough neural organization to qualify as a vertebrate, apparently a stretch for some folks these days.
    - Cecil Adams.
  • 03-26-2008 9:12 AM In reply to

    Re: the null check that follows is not redundant!

    CDarklock:
    A* A_A (A *this, /* other arguments */) { return this; } // FTFY
    Okay, if Cfront did this, the snippet'd work. But why? You're not supposed to change this, anywhere, anytime. It makes no sense! After all, what would happen if the object wasn't allocated dynamically?
    ╩юфют√ь ёЄЁрэшЎрь яюЁр эр яхэёш■.

    Visit #TDWTF @ SlashNET - the semi-official WTF IRC channel.
  • 03-26-2008 9:19 AM In reply to

    • PJH
    • Top 25 Contributor
    • Joined on 02-14-2007
    • Posts 624

    Re: the null check that follows is not redundant!

    Spectre:
    But why? You're not supposed to change this, anywhere, anytime. It makes no sense!
    Objects, under certain conditions, are allowed to 'commit suicide. Why you'd want to in general (as opposed to a saner method) is another matter..

    Placement new is another place where this is changed. 

    Spectre:
    After all, what would happen if the object wasn't allocated dynamically?
    That is not one of the certain conditions - see my other post.

     

    This is not a problem that requires infinite wisdom, Benj. This is a problem that requires enough neural organization to qualify as a vertebrate, apparently a stretch for some folks these days.
    - Cecil Adams.
  • 03-26-2008 9:45 AM In reply to

    Re: the null check that follows is not redundant!

    PJH:
    Objects, under certain conditions, are allowed to 'commit suicide.
    Yeah, I know, but this (the pointer) is not changed in the process. If one deleted the object in the constructor, new A would still return an (invalid) pointer.
    PJH:
    Placement new is another place where this is changed. 
    Wait. What? I mean, I know what the placement new is, I don't see how can it change this — the object is simply constructed where it is told to.
    ╩юфют√ь ёЄЁрэшЎрь яюЁр эр яхэёш■.

    Visit #TDWTF @ SlashNET - the semi-official WTF IRC channel.
Page 1 of 1 (16 items)
Powered by Community Server (Non-Commercial Edition), by Telligent Systems