auto_ptr and operator void*();

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rob Williscroft

    #16
    Re: auto_ptr and operator void*();

    Gianni Mariani wrote in news:bkl6u2$erh @dispatch.conce ntric.net:
    [color=blue]
    >
    > I think you're argument is lacking.
    >
    > r is an int * - the size is sizeof(int). The static_cast<int *>(q) put
    > that information you're referring to back into the pointer. Hence the
    > size of what r is pointing to is known at the time it is deleted.
    >
    > What do you think this should do ?
    >
    > int* p = new char(42);
    > void* q = static_cast<voi d*>(p);
    > MuthaObject * r = static_cast<int *>(q);
    > delete r;
    >[color=green]
    >>
    >> delete q;
    >>[/color]
    >
    > the size of what q is pointing to is not known.
    >
    >[/color]

    operator delete doesn't take size info, demo below.

    The type info in delete is (can) only be used to call the destructor.
    Also there would be little utility in banning delete (void *), as
    all it really does is call the global operator delete( void * ). It
    never needs the :: when used in a member function though.

    #include <iostream>
    #include <ostream>

    struct base
    {
    virtual ~base() {}
    void *operator new (std::size_t sz )
    {
    std::cout << "new; " << sz << std::endl;
    return ::operator new( sz );
    }

    void operator delete ( void *p )
    {
    std::cout << "deleteing; " << p << std::endl;
    ::operator delete ( p );
    }
    };

    struct derived: base
    {
    int i;
    };

    void del_base( base *b )
    {
    delete b;
    }

    int main()
    {
    base *b = new base;
    del_base( new derived );
    del_base( b );
    }

    Rob.
    --

    Comment

    • David B. Held

      #17
      Re: auto_ptr and operator void*();

      "Gianni Mariani" <gi2nospam@mari ani.ws> wrote in message
      news:bkl6u2$erh @dispatch.conce ntric.net...[color=blue]
      > [...]
      > What do you think this should do ?
      >
      > int* p = new char(42);
      > void* q = static_cast<voi d*>(p);
      > MuthaObject * r = static_cast<int *>(q);
      > delete r;[/color]

      Unless there is a defined conversion from int* to
      MuthaObject*, I think it should elicit a diagnostic.
      And if there is a conversion from int* to MuthaObject*,
      I should hope the author of such a conversion has
      taken into account this very situation.
      [color=blue][color=green]
      > > delete q;[/color]
      >
      > the size of what q is pointing to is not known.[/color]

      That's an interesting question. Theoretically, the
      compiler *could* always keep track of what void* are
      pointing to, but I'm not sure they are required to do so,
      which is probably why it results in undefined behaviour.

      Dave


      Comment

      • Gianni Mariani

        #18
        Re: auto_ptr and operator void*();

        David B. Held wrote:[color=blue]
        > "Gianni Mariani" <gi2nospam@mari ani.ws> wrote in message
        > news:bkl6u2$erh @dispatch.conce ntric.net...
        >[color=green]
        >>[...]
        >>What do you think this should do ?
        >>
        >>int* p = new char(42);
        >>void* q = static_cast<voi d*>(p);
        >>MuthaObject * r = static_cast<int *>(q);
        >>delete r;[/color]
        >
        >
        > Unless there is a defined conversion from int* to
        > MuthaObject*, I think it should elicit a diagnostic.[/color]

        Maybe, but it is perfectly legal C++ (except for a typo I just noticed).

        The point was that the pointer information is mostly compile-time, not
        run time and with casting you get to control the behaviour.
        [color=blue]
        > And if there is a conversion from int* to MuthaObject*,
        > I should hope the author of such a conversion has
        > taken into account this very situation.[/color]

        Even if there was a conversion, it would not be used because the
        conversion is from a void *.

        No question that the above code is like whacking yourself over the head
        with a 4x2. C++ (and C) let's you do that, especially when you start
        messing with type casts.
        [color=blue]
        >
        >[color=green][color=darkred]
        >>>delete q;[/color]
        >>
        >>the size of what q is pointing to is not known.[/color]
        >
        >
        > That's an interesting question. Theoretically, the
        > compiler *could* always keep track of what void* are
        > pointing to, but I'm not sure they are required to do so,
        > which is probably why it results in undefined behaviour.[/color]

        I don't think you can. There are paths of data that are outside the
        control of the conmpiler.




        Comment

        • Gianni Mariani

          #19
          Re: auto_ptr and operator void*();

          Rob Williscroft wrote:[color=blue]
          > Gianni Mariani wrote in news:bkl6u2$erh @dispatch.conce ntric.net:
          >
          >[color=green]
          >>I think you're argument is lacking.
          >>
          >>r is an int * - the size is sizeof(int). The static_cast<int *>(q) put
          >>that information you're referring to back into the pointer. Hence the
          >>size of what r is pointing to is known at the time it is deleted.
          >>
          >>What do you think this should do ?
          >>
          >>int* p = new char(42);
          >>void* q = static_cast<voi d*>(p);
          >>MuthaObject * r = static_cast<int *>(q);
          >>delete r;
          >>
          >>[color=darkred]
          >>>delete q;
          >>>[/color]
          >>
          >>the size of what q is pointing to is not known.
          >>
          >>[/color]
          >
          >
          > operator delete doesn't take size info, demo below.[/color]

          I think it does.


          #include <iostream>


          char allocator_data[1024];
          int amount_allocate d = 0;


          class Foo
          {
          public:

          void * operator new( unsigned int size )
          {
          char * ptr = ( allocator_data + amount_allocate d );
          amount_allocate d += size;

          std::cout << "Allocate size is " << size << std::endl;

          return ( void * ) ptr;
          }

          void * operator new[]( unsigned int size )
          {
          char * ptr = ( allocator_data + amount_allocate d );
          amount_allocate d += size;

          std::cout << "Allocate size is " << size << std::endl;

          return ( void * ) ptr;
          }

          void operator delete( void * ptr, unsigned int size )
          {
          std::cout << "delete size is " << size << std::endl;

          // drop memory on the floor
          }

          void operator delete[] ( void * ptr, unsigned int size )
          {
          std::cout << "delete size is " << size << std::endl;

          // drop memory on the floor
          }

          };


          class B : public Foo
          {
          public:
          int xxx;
          int yyy;
          };


          int main()
          {

          B * z = new B;

          B * k = new B[30];

          delete z;

          delete [] k;
          }

          Admittedly it's an optional parameter BUT it is available and I've seen
          some really KULE allocators that use this information when managing
          extreme numbers of tiny objects and saving big time on memory and cycles.
          [color=blue]
          >
          > The type info in delete is (can) only be used to call the destructor.[/color]

          Most of the time.
          [color=blue]
          > Also there would be little utility in banning delete (void *), as
          > all it really does is call the global operator delete( void * ). It
          > never needs the :: when used in a member function though.
          >[/color]


          delete ptr

          and

          operator delete( ptr )

          are 2 different things.

          delete ptr also calls the destructor (if it exists) while operator
          delete( ptr ) simply calls the method "operator delete( ... )".




          Comment

          • David B. Held

            #20
            Re: auto_ptr and operator void*();

            "Gianni Mariani" <gi2nospam@mari ani.ws> wrote in message
            news:bklfa4$ern @dispatch.conce ntric.net...[color=blue]
            > David B. Held wrote:[color=green]
            > > [...]
            > > Unless there is a defined conversion from int* to
            > > MuthaObject*, I think it should elicit a diagnostic.[/color]
            >
            > Maybe, but it is perfectly legal C++ (except for a typo I
            > just noticed).[/color]

            I'm not sure what's so legal about it:

            class MuthaObject { };

            int main()
            {
            MuthaObject* p = new int;
            }

            "ComeauTest .c", line 5: error: a value of type "int *" cannot
            be used to initialize an entity of type "MuthaObjec t *"
            MuthaObject* p = new int;

            [color=blue]
            > The point was that the pointer information is mostly
            > compile-time, not run time and with casting you get to
            > control the behaviour.[/color]

            Of course. What does that have to do with void*?
            [color=blue][color=green]
            > > And if there is a conversion from int* to MuthaObject*,
            > > I should hope the author of such a conversion has
            > > taken into account this very situation.[/color]
            >
            > Even if there was a conversion, it would not be used
            > because the conversion is from a void *.[/color]

            Not sure what you're talking about here. I'm talking
            about:
            [color=blue]
            > MuthaObject * r = static_cast<int *>(q);[/color]

            [color=blue][color=green]
            > > [...]
            > > That's an interesting question. Theoretically, the
            > > compiler *could* always keep track of what void* are
            > > pointing to, but I'm not sure they are required to do so,
            > > which is probably why it results in undefined behaviour.[/color]
            >
            > I don't think you can. There are paths of data that are
            > outside the control of the conmpiler.[/color]

            Such as?

            Dave


            Comment

            • Gianni Mariani

              #21
              Re: auto_ptr and operator void*();

              David B. Held wrote:[color=blue]
              > "Gianni Mariani" <gi2nospam@mari ani.ws> wrote in message
              > news:bklfa4$ern @dispatch.conce ntric.net...
              >[color=green]
              >>David B. Held wrote:
              >>[color=darkred]
              >>>[...]
              >>>Unless there is a defined conversion from int* to
              >>>MuthaObject* , I think it should elicit a diagnostic.[/color]
              >>
              >>Maybe, but it is perfectly legal C++ (except for a typo I
              >>just noticed).[/color]
              >
              >
              > I'm not sure what's so legal about it:
              >
              > class MuthaObject { };
              >
              > int main()
              > {[/color]


              This was posted (typo fixed).
              int* p = new int(42);
              void* q = static_cast<voi d*>(p);
              MuthaObject * r = static_cast<int *>(q);
              delete r;

              and you tried this ?
              [color=blue]
              > MuthaObject* p = new int;
              > }
              >
              > "ComeauTest .c", line 5: error: a value of type "int *" cannot
              > be used to initialize an entity of type "MuthaObjec t *"
              > MuthaObject* p = new int;
              >
              >[/color]

              I don't think you're testing what I posted.

              [color=blue]
              >[color=green]
              >>The point was that the pointer information is mostly
              >>compile-time, not run time and with casting you get to
              >>control the behaviour.[/color]
              >
              >
              > Of course. What does that have to do with void*?[/color]


              Maybe I mis-understood what you meant by

              "the information must be saved somewhere".

              What did you mean by that ?
              [color=blue]
              >
              >[color=green][color=darkred]
              >>>And if there is a conversion from int* to MuthaObject*,
              >>>I should hope the author of such a conversion has
              >>>taken into account this very situation.[/color]
              >>
              >>Even if there was a conversion, it would not be used
              >>because the conversion is from a void *.[/color]
              >
              >
              > Not sure what you're talking about here. I'm talking
              > about:[/color]


              Specifically, the compiler MUST NOT apply a conversion from int * to
              MuthaObject* (even if one exists) to be compliant to the standard with
              the code snippet I posted.

              [color=blue]
              >
              >[color=green]
              >>MuthaObject * r = static_cast<int *>(q);[/color]
              >
              >
              >[color=green][color=darkred]
              >>>[...]
              >>>That's an interesting question. Theoretically, the
              >>>compiler *could* always keep track of what void* are
              >>>pointing to, but I'm not sure they are required to do so,
              >>>which is probably why it results in undefined behaviour.[/color]
              >>
              >>I don't think you can. There are paths of data that are
              >>outside the control of the conmpiler.[/color]
              >
              >
              > Such as?[/color]

              Libraries, files, devices ...



              Comment

              • David B. Held

                #22
                Re: auto_ptr and operator void*();

                "Gianni Mariani" <gi2nospam@mari ani.ws> wrote in message
                news:bkm51c$qee @dispatch.conce ntric.net...[color=blue]
                > David B. Held wrote:[color=green]
                > > [...]
                > > I'm not sure what's so legal about it:
                > >
                > > class MuthaObject { };
                > >
                > > int main()
                > > {[/color]
                >
                >
                > This was posted (typo fixed).
                > int* p = new int(42);
                > void* q = static_cast<voi d*>(p);
                > MuthaObject * r = static_cast<int *>(q);
                > delete r;
                >
                > and you tried this ?
                >[color=green]
                > > MuthaObject* p = new int;
                > > }[/color]
                > [...]
                >
                > I don't think you're testing what I posted.[/color]

                I'm testing the part that I thought should cause a diagnostic
                to be emitted, which was the assignment of an int* to a
                MuthaObject*.
                [color=blue]
                > [...]
                > Maybe I mis-understood what you meant by
                >
                > "the information must be saved somewhere".
                >
                > What did you mean by that ?[/color]

                I mean the compiler must keep track of pointer type
                information somewhere in order to do valid casts to void*
                and back. But technically, I guess that's not the case.
                The compiler could just assume that you perform casts
                correctly, and invoke undefined behaviour if you don't.
                [color=blue]
                > [...]
                > Specifically, the compiler MUST NOT apply a
                > conversion from int * to MuthaObject* (even if one
                > exists) to be compliant to the standard with the code
                > snippet I posted.[/color]

                So what's your point?
                [color=blue][color=green][color=darkred]
                > >>[...]
                > >>I don't think you can. There are paths of data that are
                > >>outside the control of the conmpiler.[/color]
                > >
                > > Such as?[/color]
                >
                > Libraries, files, devices ...[/color]

                I don't think you can read pointers from a file and expect
                them to work properly, but I will buy that a pointer passed
                over a DLL/so boundary will probably not have any
                special type information.

                Dave


                Comment

                • Rob Williscroft

                  #23
                  Re: auto_ptr and operator void*();

                  Gianni Mariani wrote in news:bklgki$erj @dispatch.conce ntric.net:
                  [color=blue]
                  > Rob Williscroft wrote:[color=green]
                  >> Gianni Mariani wrote in news:bkl6u2$erh @dispatch.conce ntric.net:
                  >>
                  >>[color=darkred]
                  >>>I think you're argument is lacking.
                  >>>
                  >>>r is an int * - the size is sizeof(int). The static_cast<int *>(q)
                  >>>put that information you're referring to back into the pointer. Hence
                  >>>the size of what r is pointing to is known at the time it is deleted.
                  >>>
                  >>>What do you think this should do ?
                  >>>
                  >>>int* p = new char(42);
                  >>>void* q = static_cast<voi d*>(p);
                  >>>MuthaObjec t * r = static_cast<int *>(q);
                  >>>delete r;
                  >>>
                  >>>
                  >>>>delete q;
                  >>>>
                  >>>
                  >>>the size of what q is pointing to is not known.
                  >>>
                  >>>[/color]
                  >>
                  >>
                  >> operator delete doesn't take size info, demo below.[/color]
                  >
                  > I think it does.
                  >[/color]

                  [snip]

                  Thanks for the code, as an aside I got:
                  <aside>

                  bcc32:
                  Allocate size is 16
                  Allocate size is 480
                  delete size is 16
                  delete [] size is 16

                  g++:
                  Allocate size is 8
                  Allocate size is 244
                  delete size is 8
                  delete size is 244

                  cl:
                  Allocate size is 8
                  Allocate size is 240
                  delete size is 8
                  delete [] size is 8

                  g++ takes an extra 4 bytes for the size-of info it passes back.

                  1 out of 3 got delete [] right. I mostly consider cl to be my most
                  conforming compiler ( It does 2-Phase lookup if you prod it just right )
                  but then gcc comes along and does this.

                  </aside>[color=blue]
                  >
                  > Admittedly it's an optional parameter[/color]

                  Size info never gets passed on to the to ::operator delete i.e. the
                  inbuilt "free-store" has to retain any size-of information that it might
                  require.

                  In general a compiler has to be able to compile delete expresions
                  where it is unable to pass size or any other info other than the
                  pointer to operator delete.
                  [color=blue]
                  > BUT it is available and I've seen
                  > some really KULE allocators that use this information when managing
                  > extreme numbers of tiny objects and saving big time on memory and
                  > cycles.
                  >[color=green]
                  >>
                  >> The type info in delete is (can) only be used to call the destructor.[/color]
                  >
                  > Most of the time.
                  >[color=green]
                  >> Also there would be little utility in banning delete (void *), as
                  >> all it really does is call the global operator delete( void * ). It
                  >> never needs the :: when used in a member function though.
                  >>[/color]
                  >
                  >
                  > delete ptr
                  >
                  > and
                  >
                  > operator delete( ptr )
                  >
                  > are 2 different things.
                  >
                  > delete ptr also calls the destructor (if it exists) while operator
                  > delete( ptr ) simply calls the method "operator delete( ... )".
                  >
                  >[/color]

                  delete (void *)ptr; will call ::operator delete( ptr ) and nothing else.
                  It will do this even when in a class scope that defines a member
                  operator delete.

                  Rob.
                  --

                  Comment

                  • Sektor van Skijlen

                    #24
                    Re: auto_ptr and operator void*();

                    Marcin Vorbrodt <mvorbro@eos.nc su.edu> wrote:
                    # Is there any reason why auto_ptr does not have the cast operator like this:

                    # operator void* ();

                    # So that one could easily test auto_ptr for NULL ???
                    # Standard does not declare such operator.

                    Right. Moreover, such an operator will not allow you to compare the inside
                    pointer against NULL. At least because NULL is not a 'void*' value, but
                    'int' value.

                    To be able to compare the inside pointer against NULL, the auto_ptr template
                    had to provide appropriate '==' operator with 'int' as an argument. This also
                    does not matter if you use the deprecated NULL constant, or - as recommended
                    - directly 0.

                    I think also that this problem is wider and is a more global problem with
                    null pointer value. Neither 0 nor NULL is a good way to check the pointer
                    against null pointer value. You can find a better definition of 'null'
                    symbol at:



                    Search for "NULL" string there; the definition is below that line.
                    (any suggestions welcome ;)


                    # Is the only way to check if auto_ptr points to NULL, is to use .get() method
                    # ?

                    By standard methods, yes.


                    --
                    1 6 1 7 4 4 2 548 g4bc7a4 66z 3xt7w v1y z9p1 120 32
                    (( Michal "Sektor" Malecki w4 66 64 73 7564 24 5 v 34 4
                    )) ektor van Skijlen 1 5 5 1 844 a v r z 4
                    Software engineer, Motorola GSG Poland 1 2 2a 1 4
                    WARNING: Opinions presented by me on usenet groups are my personal opinions
                    ONLY and are not connected to the employer.

                    Comment

                    • Ron Natalie

                      #25
                      Re: auto_ptr and operator void*();


                      "Sektor van Skijlen" <sektor@hasiok. org> wrote in message news:bkpem8$rid $1@newshost.mot .com...
                      [color=blue]
                      > Right. Moreover, such an operator will not allow you to compare the inside
                      > pointer against NULL. At least because NULL is not a 'void*' value, but
                      > 'int' value.[/color]

                      Huh? Of coruse it's not a void* value, but it's comparable to one. An
                      arbitrary object pointer that is a null pointer, converted to another object pointer
                      (like void*) is the null pointer and can be compared against the null pointer
                      constant (NULL).
                      [color=blue]
                      >
                      > To be able to compare the inside pointer against NULL, the auto_ptr template
                      > had to provide appropriate '==' operator with 'int' as an argument. This also
                      > does not matter if you use the deprecated NULL constant, or - as recommended
                      > - directly 0.[/color]

                      Nonsense, the overload would not be needed. NULL is NOT deprecated.
                      [color=blue]
                      > I think also that this problem is wider and is a more global problem with
                      > null pointer value. Neither 0 nor NULL is a good way to check the pointer
                      > against null pointer value.[/color]

                      It works, the major problem is that it's confusable with integers in overloading
                      contexts.

                      You can find a better definition of 'null'[color=blue]
                      > symbol at:
                      >
                      > http://www.intercon.pl/~sektor/cbx/g...templates.html[/color]

                      I don't speak Polish.


                      Comment

                      Working...