Virtual Methods Question

Discussion in 'C++' started by Daniel, Feb 27, 2006.

  1. Daniel

    Daniel Guest

    I have the following three classes

    class A
    {
    public:
    virtual void f() = 0;
    };

    class B: public A
    {
    public:
    virtual void f();
    };

    void B::f()
    {
    cout << "B::f()";
    }

    class C: public B
    {
    public:
    void f();
    };

    void C::f()
    {
    cout << "C::f()";
    }


    main()
    {
    A* x = new C();

    x->f();
    }

    The above program prints the following:

    B::f()

    But, I wanted the program to print

    C::f()

    Why is the program doing this? Is there any way for me to have C's f()
    method invoked instead of B's f() method? I am using the GNU compiler
    for VxWorks 5.5. Thanks in advance for any help.


    -Daniel
     
    Daniel, Feb 27, 2006
    #1
    1. Advertising

  2. Daniel

    Guest

    Daniel wrote:

    > The above program prints the following:
    >
    > B::f()
    >
    > But, I wanted the program to print
    >
    > C::f()


    prints "C::f()" over here. That is what it should do.
     
    , Feb 27, 2006
    #2
    1. Advertising

  3. "Daniel" <> schrieb im Newsbeitrag
    news:...

    > class C: public B
    > {
    > public:
    > void f();
    > };


    you miss a virtual there.

    f~
     
    Frank Schmidt, Feb 27, 2006
    #3
  4. Daniel

    Peter_Julian Guest

    "Frank Schmidt" <> wrote in message
    news:dttrvp$ndp$...
    |
    | "Daniel" <> schrieb im Newsbeitrag
    | news:...
    |
    | > class C: public B
    | > {
    | > public:
    | > void f();
    | > };
    |
    | you miss a virtual there.
    |
    | f~
    |

    Nope, if the pure-abstract or base class specifies that void f() is virtual
    then its virtual in the entire hierarchy. Regardless whether the derived
    classes have that function as virtual or not.
     
    Peter_Julian, Feb 27, 2006
    #4
  5. Daniel

    Guest

    Peter_Julian wrote:
    > "Frank Schmidt" <> wrote in message
    > news:dttrvp$ndp$...
    > |
    > | "Daniel" <> schrieb im Newsbeitrag
    > | news:...
    > |
    > | > class C: public B
    > | > {
    > | > public:
    > | > void f();
    > | > };
    > |
    > | you miss a virtual there.
    > |
    > | f~
    > |
    >
    > Nope, if the pure-abstract or base class specifies that void f() is virtual
    > then its virtual in the entire hierarchy. Regardless whether the derived
    > classes have that function as virtual or not.


    I thought it stopped at C meaning that any subclass of C would not be
    able to polymorphically override f().
     
    , Feb 27, 2006
    #5
  6. Daniel

    Peter_Julian Guest

    "Daniel" <> wrote in message
    news:...
    | I have the following three classes
    |
    | class A
    | {
    | public:
    | virtual void f() = 0;
    | };

    undefined behaviour.
    1) you failed to invoke delete x
    2) In main() you are using a base pointer to a derived object and yet you
    have not declared a virtual destructor in class A.

    #include <iostream>
    #include <ostream>

    class A
    {
    public:
    virtual ~A() { std::cout << "~A()\n"; }
    virtual void f() = 0;
    };

    <snip>

    |
    | main()

    int main()

    | {
    | A* x = new C();

    A* x = new C;

    |
    | x->f();

    delete x;

    | }
    |
    | The above program prints the following:
    |
    | B::f()
    |
    | But, I wanted the program to print
    |
    | C::f()
    |
    | Why is the program doing this? Is there any way for me to have C's f()
    | method invoked instead of B's f() method? I am using the GNU compiler
    | for VxWorks 5.5. Thanks in advance for any help.
    |

    Your compiler is invoking the C() ctor correctly(which requires that both
    A() and B() get allocated first) and then drops the allocation of the
    derived C as if it were a temporary (which is not appropriate but otherwise
    not strictly enforced). The remnant is a valid B-type object.

    That should be fixed with the correct statement:
    A* x = new C; // correctly invokes the default ctor to completion

    Note that your problem, other than not using delete x at all (shame), has a
    much more critical issue than the one you raise. If you don't provide a
    virtual d~tor in class A then ~B() or ~C() will never be invoked. Thats a
    guarenteed memory leak.

    Test it:

    int main()
    {
    A* x = new C;

    x->f();

    delete x;

    return 0;
    }

    /* correct output
    C::f()
    ~C()
    ~B()
    ~A()
    */

    but what you are getting with the compiler generated d~tor(s) is:

    C::f()
    ~A()

    which is a partial destruction and a memory leak. bad news.

    Moral of the story:

    a) never, ever new if you don't delete
    b) never, ever new[] if you don't [] delete
    c)if you derive and destroy via a pointer to base:
    ***always provide a virtual d~tor***
    or suffer the consequences.
     
    Peter_Julian, Feb 27, 2006
    #6
  7. Daniel

    Peter_Julian Guest

    <> wrote in message
    news:...
    |
    | Peter_Julian wrote:
    | > "Frank Schmidt" <> wrote in message
    | > news:dttrvp$ndp$...
    | > |
    | > | "Daniel" <> schrieb im Newsbeitrag
    | > | news:...
    | > |
    | > | > class C: public B
    | > | > {
    | > | > public:
    | > | > void f();
    | > | > };
    | > |
    | > | you miss a virtual there.
    | > |
    | > | f~
    | > |
    | >
    | > Nope, if the pure-abstract or base class specifies that void f() is
    virtual
    | > then its virtual in the entire hierarchy. Regardless whether the derived
    | > classes have that function as virtual or not.
    |
    | I thought it stopped at C meaning that any subclass of C would not be
    | able to polymorphically override f().
    |

    That doesn't make sense, and with good reason. The is_a relationship is
    critical here. If you publicly derive from C and declare D, then its implied
    that the D-type is_a C-type as well. You can perfectly well derive like
    so...

    class D : public C
    {
    };

    and never declare void f() since a call like so...

    A* p_a = new D;
    p_a->f(); // will call C::f(), no problem - its expected
    delete p_a; // invokes 4 d~tors - ~D, ~C, ~B and ~A

    If there was a way to prevent the inheritance of a pure-virtual member
    function, polymorphism would be broken. And there is...
    ___
    The answer to your quest is simple: composition or private inheritance.
    Sometimes its more important to understand when not_to_use polymorphic
    inheritance.
    Neither of these represent an "is_a" inheritance scheme.

    class D
    {
    C c;
    public:
    void f() { } // not virtual
    };

    or D in_terms_of C, where D is_not C or B or A. This is also a form of
    composition, not polymorphic inheritance...

    class D : private C
    {
    void f() { std::cout << "D::f()\n"; } // not virtual
    };

    int main()
    {
    D d;
    d.f();
    }

    /*
    D::f() // not virtual
    ~D()
    ~C()
    ~B()
    ~A()
    */
     
    Peter_Julian, Feb 27, 2006
    #7
  8. Daniel wrote:
    > The above program prints the following:
    >
    > B::f()


    You must have made a copying error: the program does not compile
    for me. There are missing include statements, namespace qualification,
    and a missing return type of 'main()'. Once I fixed these problems,
    the program prints "C::f()", as it should.
    --
    <mailto:> <http://www.dietmar-kuehl.de/>
    <http://www.eai-systems.com> - Efficient Artificial Intelligence
     
    Dietmar Kuehl, Feb 27, 2006
    #8
  9. "Peter_Julian" <> schrieb im Newsbeitrag
    news:fNuMf.1551$...
    >
    > "Frank Schmidt" <> wrote in message
    > news:dttrvp$ndp$...
    > |
    > | "Daniel" <> schrieb im Newsbeitrag
    > | news:...
    > |
    > | > class C: public B
    > | > {
    > | > public:
    > | > void f();
    > | > };
    > |
    > | you miss a virtual there.
    > |
    > | f~
    > |
    >
    > Nope, if the pure-abstract or base class specifies that void f() is
    > virtual
    > then its virtual in the entire hierarchy. Regardless whether the derived
    > classes have that function as virtual or not.


    say that to a compiler, which calls B::f() with the given the source
     
    Frank Schmidt, Feb 27, 2006
    #9
  10. Daniel

    Guest

    Peter_Julian wrote:
    > <> wrote in message
    > news:...
    > |
    > | Peter_Julian wrote:
    > | > "Frank Schmidt" <> wrote in message
    > | > news:dttrvp$ndp$...
    > | > |
    > | > | "Daniel" <> schrieb im Newsbeitrag
    > | > | news:...
    > | > |
    > | > | > class C: public B
    > | > | > {
    > | > | > public:
    > | > | > void f();
    > | > | > };
    > | > |
    > | > | you miss a virtual there.
    > | > |
    > | > | f~
    > | > |
    > | >
    > | > Nope, if the pure-abstract or base class specifies that void f() is
    > virtual
    > | > then its virtual in the entire hierarchy. Regardless whether the derived
    > | > classes have that function as virtual or not.
    > |
    > | I thought it stopped at C meaning that any subclass of C would not be
    > | able to polymorphically override f().
    > |
    >
    > That doesn't make sense, and with good reason. The is_a relationship is
    > critical here. If you publicly derive from C and declare D, then its implied
    > that the D-type is_a C-type as well. You can perfectly well derive like
    > so...
    >
    > class D : public C
    > {
    > };
    >
    > and never declare void f() since a call like so...


    You totally missed my point. Doesn't matter because I was wrong but
    still, I said one thing and you went off in a totally different
    direction.
     
    , Feb 27, 2006
    #10
  11. Daniel

    Peter_Julian Guest

    "Frank Schmidt" <> wrote in message
    news:dtutag$i83$...
    |
    | "Peter_Julian" <> schrieb im Newsbeitrag
    | news:fNuMf.1551$...
    | >
    | > "Frank Schmidt" <> wrote in message
    | > news:dttrvp$ndp$...
    | > |
    | > | "Daniel" <> schrieb im Newsbeitrag
    | > | news:...
    | > |
    | > | > class C: public B
    | > | > {
    | > | > public:
    | > | > void f();
    | > | > };
    | > |
    | > | you miss a virtual there.
    | > |
    | > | f~
    | > |
    | >
    | > Nope, if the pure-abstract or base class specifies that void f() is
    | > virtual
    | > then its virtual in the entire hierarchy. Regardless whether the derived
    | > classes have that function as virtual or not.
    |
    | say that to a compiler, which calls B::f() with the given the source
    |

    Wrong solution. The only reason that B::f() is being called is because the
    call to new C() never return a type C instance [undefined behaviour]. The
    remnant type at the pointer is a B-type object with some compilers.

    The correct statement is: A* p = new C; // no brackets

    insofar as the virtual keyword, test it yourself...:

    ___
    #include <iostream>
    #include <ostream>

    class A
    {
    virtual void f();
    };

    class B : public A
    {
    void f();
    };

    class C : public B
    {
    void f();
    };

    int main()
    {
    C c;
    A* p = &c;
    p->f();

    return 0;
    }

    /*
    C::f()
    */
     
    Peter_Julian, Feb 28, 2006
    #11
  12. Daniel

    Jay_Nabonne Guest

    On Sun, 26 Feb 2006 17:34:58 -0800, Daniel wrote:

    > I have the following three classes


    <snip>

    >
    > The above program prints the following:
    >
    > B::f()
    >
    > But, I wanted the program to print
    >
    > C::f()
    >
    > Why is the program doing this? Is there any way for me to have C's f()
    > method invoked instead of B's f() method?


    The way the code is set up above, it should work. Make sure the function
    signatures are *identical* including parameters, return type, and
    "const"ness.

    - jay
     
    Jay_Nabonne, Feb 28, 2006
    #12
  13. Daniel

    Jay_Nabonne Guest

    On Sun, 26 Feb 2006 23:50:54 -0500, Peter_Julian wrote:

    I'll probably regret this...

    >
    > "Daniel" <> wrote in message
    > news:...
    > | I have the following three classes
    > |
    > | class A
    > | {
    > | public:
    > | virtual void f() = 0;
    > | };
    >
    > undefined behaviour.
    > 1) you failed to invoke delete x


    Failing to delete x is not undefined behavior. It's a memory leak.

    > 2) In main() you are using a base pointer to a derived object and yet you
    > have not declared a virtual destructor in class A.


    *Using* a derived object through a base pointer (without a virtual
    destructor) is not undefined behavior (see, for example, COM). *Deleting*
    said pointer would be. Since the pointer was not deleted, there is no
    undefined behavior. (But as soon as you add your delete, then you need to
    add the virtual destructor.) I'm not saying it's good code (and you
    provide an excellent analysis below), but there's no undefined behavior as
    is.

    >
    >
    > | {
    > | A* x = new C();
    >
    > A* x = new C;
    >


    There is no difference in the above two lines for the C class, at least as
    far as the stability of the resulting object goes.

    >
    > Your compiler is invoking the C() ctor correctly(which requires that both
    > A() and B() get allocated first) and then drops the allocation of the
    > derived C as if it were a temporary (which is not appropriate but otherwise
    > not strictly enforced). The remnant is a valid B-type object.


    Have you been smoking the C++ standard again? ;) Seriously, what are you
    talking about? What in the world would cause the newly allocated "C"
    object to decay to a "B"?

    - Jay
     
    Jay_Nabonne, Feb 28, 2006
    #13
  14. Daniel

    Peter_Julian Guest

    "Jay_Nabonne" <> wrote in message
    news:p...
    | On Sun, 26 Feb 2006 17:34:58 -0800, Daniel wrote:
    |
    | > I have the following three classes
    |
    | <snip>
    |
    | >
    | > The above program prints the following:
    | >
    | > B::f()
    | >
    | > But, I wanted the program to print
    | >
    | > C::f()
    | >
    | > Why is the program doing this? Is there any way for me to have C's f()
    | > method invoked instead of B's f() method?
    |
    | The way the code is set up above, it should work. Make sure the function
    | signatures are *identical* including parameters, return type, and
    | "const"ness.
    |

    The return type is not part of the signature and is not taken in
    consideration when deciding which function gets called.
     
    Peter_Julian, Mar 1, 2006
    #14
  15. Daniel

    Peter_Julian Guest

    "Jay_Nabonne" <> wrote in message
    news:p...
    | On Sun, 26 Feb 2006 23:50:54 -0500, Peter_Julian wrote:
    |
    | I'll probably regret this...

    lol, no we won't, i welcome the feedback specially if it proves me wrong

    |
    | >
    | > "Daniel" <> wrote in message
    | > news:...
    | > | I have the following three classes
    | > |
    | > | class A
    | > | {
    | > | public:
    | > | virtual void f() = 0;
    | > | };
    | >
    | > undefined behaviour.
    | > 1) you failed to invoke delete x
    |
    | Failing to delete x is not undefined behavior. It's a memory leak.

    The mem leak wasn't what made the code UB.

    |
    | > 2) In main() you are using a base pointer to a derived object and yet
    you
    | > have not declared a virtual destructor in class A.
    |
    | *Using* a derived object through a base pointer (without a virtual
    | destructor) is not undefined behavior (see, for example, COM). *Deleting*
    | said pointer would be. Since the pointer was not deleted, there is no
    | undefined behavior. (But as soon as you add your delete, then you need to
    | add the virtual destructor.) I'm not saying it's good code (and you
    | provide an excellent analysis below), but there's no undefined behavior as
    | is.

    Wrong, new used to allocate that base pointer, whether its explicitly
    deleted or not, is UB. Consider: shared_ptr<T>, scoped_ptr<T>, etc.

    |
    | >
    | >
    | > | {
    | > | A* x = new C();
    | >
    | > A* x = new C;
    | >
    |
    | There is no difference in the above two lines for the C class, at least as
    | far as the stability of the resulting object goes.

    This, unfortunately, has been proven to be false. The OP's result is a case
    in point.

    |
    | >
    | > Your compiler is invoking the C() ctor correctly(which requires that
    both
    | > A() and B() get allocated first) and then drops the allocation of the
    | > derived C as if it were a temporary (which is not appropriate but
    otherwise
    | > not strictly enforced). The remnant is a valid B-type object.
    |
    | Have you been smoking the C++ standard again? ;) Seriously, what are you
    | talking about? What in the world would cause the newly allocated "C"
    | object to decay to a "B"?
    |

    Beats the hell out of me (placement new implementation?). Won't be the first
    time i've seen that. It is, however, correct to write ...

    int* p = new int;

    .... to invoke the default ctor. Even the problem compilers handle that
    correctly. I'ld be interested to know what that GNU compiler for VxWorks 5.5
    does without the brackets (hint?).

    [Hmm, now where the hell is that pint of beer()?]
     
    Peter_Julian, Mar 1, 2006
    #15
  16. Daniel

    Jay_Nabonne Guest

    On Tue, 28 Feb 2006 19:56:44 -0500, Peter_Julian wrote:

    >
    > "Jay_Nabonne" <> wrote in message
    > news:p...
    > | On Sun, 26 Feb 2006 17:34:58 -0800, Daniel wrote:
    > |
    > | > I have the following three classes
    > |
    > | <snip>
    > |
    > | >
    > | > The above program prints the following:
    > | >
    > | > B::f()
    > | >
    > | > But, I wanted the program to print
    > | >
    > | > C::f()
    > | >
    > | > Why is the program doing this? Is there any way for me to have C's f()
    > | > method invoked instead of B's f() method?
    > |
    > | The way the code is set up above, it should work. Make sure the function
    > | signatures are *identical* including parameters, return type, and
    > | "const"ness.
    > |
    >
    > The return type is not part of the signature and is not taken in
    > consideration when deciding which function gets called.


    In general, you are right, but I'm not sure how that relates to this
    problem.

    Since the function call is through the A*, there is only one
    function signature to examine (the one in A). As it turns out, if the
    virtual function in C had a different return type, it wouldn't compile
    anyway, so my suggestion to check the return type doesn't help here. But
    the rest are valid. For example, this code prints "B" because the function
    "f" in class C doesn't match the signature of the base class:

    class A
    {
    public:
    virtual void f() = 0;
    };

    class B : public A
    {
    virtual void f()
    {
    printf("B\n");
    }
    };

    class C : public B
    {
    void f() const
    {
    printf("C\n");
    }
    };

    int main()
    {
    A* p = new C;
    p->f();
    return 0;
    }

    - Jay
     
    Jay_Nabonne, Mar 1, 2006
    #16
  17. Daniel

    Jay_Nabonne Guest

    On Tue, 28 Feb 2006 22:45:18 -0500, Peter_Julian wrote:

    >
    > "Jay_Nabonne" <> wrote in message
    > news:p...
    > | On Sun, 26 Feb 2006 23:50:54 -0500, Peter_Julian wrote:
    > |
    > | I'll probably regret this...
    >
    > lol, no we won't, i welcome the feedback specially if it proves me wrong
    >
    > |
    > | >
    > | > "Daniel" <> wrote in message
    > | > news:...
    > | > | I have the following three classes
    > | > |
    > | > | class A
    > | > | {
    > | > | public:
    > | > | virtual void f() = 0;
    > | > | };
    > | >
    > | > undefined behaviour.
    > | > 1) you failed to invoke delete x
    > |
    > | Failing to delete x is not undefined behavior. It's a memory leak.
    >
    > The mem leak wasn't what made the code UB.
    >
    > |
    > | > 2) In main() you are using a base pointer to a derived object and yet
    > you
    > | > have not declared a virtual destructor in class A.
    > |
    > | *Using* a derived object through a base pointer (without a virtual
    > | destructor) is not undefined behavior (see, for example, COM). *Deleting*
    > | said pointer would be. Since the pointer was not deleted, there is no
    > | undefined behavior. (But as soon as you add your delete, then you need to
    > | add the virtual destructor.) I'm not saying it's good code (and you
    > | provide an excellent analysis below), but there's no undefined behavior as
    > | is.
    >
    > Wrong, new used to allocate that base pointer, whether its explicitly
    > deleted or not, is UB. Consider: shared_ptr<T>, scoped_ptr<T>, etc.


    Can you provide a reference for that statement? Since no shared_ptr or
    scoped_ptr are used here, they're irrelevant. How is allocating the
    derived object and not freeing it UB?

    >
    >
    >
    >
    > | > | {
    > | > | A* x = new C();
    > | >
    > | > A* x = new C;
    > | >
    > | >
    > | There is no difference in the above two lines for the C class, at
    > | least as far as the stability of the resulting object goes.
    >
    > This, unfortunately, has been proven to be false. The OP's result is a
    > case in point.


    The following code works fine for me (prints "C"):

    class A
    {
    public:
    virtual void f() = 0;
    };

    class B : public A
    {
    virtual void f()
    {
    printf("B\n");
    }
    };

    class C : public B
    {
    void f() const
    {
    printf("C\n");
    }
    };

    int main()
    {
    A* p = new C();
    p->f();
    return 0;
    }

    which implies either the OP was using different code or the compiler is
    broken.

    >
    >
    >
    > | > Your compiler is invoking the C() ctor correctly(which requires that
    > both
    > | > A() and B() get allocated first) and then drops the allocation of
    > | > the derived C as if it were a temporary (which is not appropriate
    > | > but
    > otherwise
    > | > not strictly enforced). The remnant is a valid B-type object.
    > |
    > | Have you been smoking the C++ standard again? ;) Seriously, what are
    > | you talking about? What in the world would cause the newly allocated
    > | "C" object to decay to a "B"?
    > |
    > |
    > Beats the hell out of me (placement new implementation?). Won't be the
    > first time i've seen that. It is, however, correct to write ...
    >
    > int* p = new int;
    >
    > ... to invoke the default ctor. Even the problem compilers handle that
    > correctly. I'ld be interested to know what that GNU compiler for VxWorks
    > 5.5 does without the brackets (hint?).


    If you're suggesting it's a compiler error, then I can get in line with
    it. I thought you were suggesting that:

    A* p = new C();

    could (with a correct implementation) be different than:

    A* p = new C;

    which is not a true statement, to my knowledge and experience.

    - Jay
     
    Jay_Nabonne, Mar 1, 2006
    #17
  18. Daniel

    Peter_Julian Guest

    "Jay_Nabonne" <> wrote in message
    news:p...
    | On Tue, 28 Feb 2006 19:56:44 -0500, Peter_Julian wrote:
    |
    | >
    | > "Jay_Nabonne" <> wrote in message
    | > news:p...
    | > | On Sun, 26 Feb 2006 17:34:58 -0800, Daniel wrote:
    | > |

    <snip>

    |
    | Since the function call is through the A*, there is only one
    | function signature to examine (the one in A). As it turns out, if the
    | virtual function in C had a different return type, it wouldn't compile
    | anyway, so my suggestion to check the return type doesn't help here. But
    | the rest are valid. For example, this code prints "B" because the function
    | "f" in class C doesn't match the signature of the base class:
    |
    | class A
    | {
    | public:
    | virtual void f() = 0;
    | };
    |
    | class B : public A
    | {
    | virtual void f()
    | {
    | printf("B\n");
    | }
    | };
    |
    | class C : public B
    | {
    | void f() const
    | {
    | printf("C\n");
    | }
    | };
    |
    | int main()
    | {
    | A* p = new C; // undefined behaviour
    | p->f();
    | return 0;
    | }
    |
    | - Jay

    Non-const member functions have a default this parameter. Adding the const
    modifier simply strips away the this parameter. So f() in C does not have
    the same signature. Its got nothing to do with the return type.

    Every cycle through the above program will leak memory since delete p was
    never called to invoke C's d~tor (of course, debug mode may help depending
    on your debugger). If you still don't think thats undefined behaviour: write
    a function that leaks a new allocation and loop through it a few thousand
    times in release mode.

    Anything could happen, it may format your hard drive, it might crash your
    OS, it may do nothing else except lower your resources. That, in effect, is
    the definition of undefined behaviour.
     
    Peter_Julian, Mar 5, 2006
    #18
  19. Daniel

    Jay_Nabonne Guest

    On Sun, 05 Mar 2006 02:11:19 -0500, Peter_Julian wrote:

    <snip>

    | A* p = new C; // undefined behaviour

    Please explain. I don't think I'm asking for much. Just justification for
    your statements. :)

    >
    > Non-const member functions have a default this parameter. Adding the const
    > modifier simply strips away the this parameter. So f() in C does not have
    > the same signature. Its got nothing to do with the return type.


    I don't recall saying it did. I was pointing out (hopefully for the OP's
    benefit) that having difference of const can cause the behavior he was
    seeing. (I once helped someone solve exactly that problem, which is why
    I'm pointing it out.)

    >
    > Every cycle through the above program will leak memory since delete p was
    > never called to invoke C's d~tor (of course, debug mode may help depending
    > on your debugger). If you still don't think thats undefined behaviour: write
    > a function that leaks a new allocation and loop through it a few thousand
    > times in release mode.


    I don't think it's "undefined behavior" in the strict C++ sense, no. If
    there is a place in the C++ specification that contradicts that, then I'm
    more than willing to change my thoughts.

    >
    > Anything could happen, it may format your hard drive, it might crash your
    > OS, it may do nothing else except lower your resources. That, in effect, is
    > the definition of undefined behaviour.


    There's "undefined behavior" in the English sense, and there's "undefined
    behavior" in the C++ sense. Cases of the latter are explictly called out
    in the specification. Again, please state where a memory leak is called
    out as C++ undefined behavior in the specification.

    I've said all I plan to on this (short of retracting my statements if
    disproved by the specification). You seem to be dodging my requests for
    you to validate your statements, and I don't see any gain to asking you
    any further.

    - Jay
     
    Jay_Nabonne, Mar 6, 2006
    #19
  20. Daniel

    Jay_Nabonne Guest

    On Sun, 05 Mar 2006 02:11:19 -0500, Peter_Julian wrote:

    One more thought...

    >
    > Every cycle through the above program will leak memory since delete p was
    > never called to invoke C's d~tor (of course, debug mode may help depending
    > on your debugger). If you still don't think thats undefined behaviour: write
    > a function that leaks a new allocation and loop through it a few thousand
    > times in release mode.
    >
    > Anything could happen, it may format your hard drive, it might crash your
    > OS, it may do nothing else except lower your resources. That, in effect, is
    > the definition of undefined behaviour.


    Consider the following code:

    #include <list>

    typedef std::list<unsigned char*> MyList;

    int main()
    {
    MyList l;

    // Allocate the world.
    try
    {
    for (;;)
    {
    l.push_back(new unsigned char[1024]);
    }
    }
    catch(...)
    {
    }

    // Release the world.
    for (MyList::iterator i = l.begin(); i != l.end(); ++i)
    {
    delete [] *l;
    }
    }

    This code will (in theory) use up a tremendous amount of memory, only
    stopping when it is no longer able to allocate memory. Following the logic
    you expressed above, since it's unclear what the OS will do when it gets
    low on memory, then the above code exhibits "undefined behavior" (I'm
    setting up the same conditions, more or less, that the offending
    non-delete code had). It could, according to you, format the hard drive.

    And yet (assuming I coded it right off the top of my head) all new's are
    paired with delete's. So how to identify the "undefined behavior"?

    Again, even though the effect of the above code on an OS is not
    necessarily predictable, it is not "undefined behavior" as defined by the
    C++ standard. So the effect of a memory leak on the OS is immaterial since
    the above code, which has no undefined behavior as defined by the C++ spec
    duplicates the conditions you described.

    - Jay
     
    Jay_Nabonne, Mar 6, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Derek Simmons
    Replies:
    0
    Views:
    826
    Derek Simmons
    Aug 1, 2004
  2. Jim Fischer
    Replies:
    3
    Views:
    462
    Jim Fischer
    Jul 31, 2003
  3. Rhino
    Replies:
    49
    Views:
    1,064
  4. Kenneth McDonald
    Replies:
    5
    Views:
    373
    Kenneth McDonald
    Sep 26, 2008
  5. Replies:
    6
    Views:
    475
Loading...

Share This Page