0

I found some places in visual studio headers where memory is freed via pointer to void.

xlocnum file:

template<class _Elem>
     class numpunct
            : public locale::facet
    { 
     _PROTECTED:
     _VIRTUAL __CLR_OR_THIS_CALL ~numpunct()
     {       // destroy the object
         _Tidy();
     }
     ...
     protected:
        void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj)
        {       // initialize from _Lobj
            _Grouping = 0;
            _Falsename = 0;
            _Truename = 0;

            _TRY_BEGIN
            _Grouping = _MAKLOCSTR(char, _Ptr->grouping, _Lobj._Getcvt());
            _Falsename = _MAKLOCSTR(_Elem, _Lobj._Getfalse(), _Lobj._Getcvt());
            _Truename = _MAKLOCSTR(_Elem, _Lobj._Gettrue(), _Lobj._Getcvt());
            _CATCH_ALL
            _Tidy();
            _RERAISE;
            _CATCH_END
             ...
            }
      ...
      private:
      void __CLR_OR_THIS_CALL _Tidy()
      {       // free all storage
         _DELETE_CRT_VEC((void *)_Grouping);
         _DELETE_CRT_VEC((void *)_Falsename);
         _DELETE_CRT_VEC((void *)_Truename);
      }
    ... 
    const char *_Grouping;  // grouping string, "" for "C" locale
    const _Elem *_Falsename;// name for false, "false" for "C" locale
    const _Elem *_Truename; // name for true, "true" for "C" locale
    };

or another one example in xlocale:

template<> class _CRTIMP2_PURE ctype<char>
    : public ctype_base
    {
       public:
          explicit __CLR_OR_THIS_CALL ctype(const mask *_Table = 0,
              bool _Deletetable = false,
              size_t _Refs = 0)
              : ctype_base(_Refs)
                {       // construct with specified table and delete flag for table
                   ...
                   if (_Table != 0)
                   {       // replace existing char to mask table
                       _Tidy();
                       _Ctype._Table = _Table;
                       _Ctype._Delfl = _Deletetable ? -1 : 0;
                   }
                }
        protected:
           void __CLR_OR_THIS_CALL _Tidy()
           {       // free any allocated storage
              if (0 < _Ctype._Delfl)
                   free((void *)_Ctype._Table);
              else if (_Ctype._Delfl < 0)
                    delete[] (void *)_Ctype._Table;
            }
    }

As were noted at https://stackoverflow.com/a/941959/1549256 deleting via a void pointer is undefined by the C++ Standard.

Why is it correct to free memrory in such cases?

Community
  • 1
  • 1
Alex
  • 2,361
  • 1
  • 20
  • 27

2 Answers2

4

The code in the standard library implementation does not have to conform to the language definition. It can take advantage of knowledge of the implementation; that's why it comes with the compiler.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • +1 for authoritative answer (I guess chances are that you may have been involved with the code in question!). but this leaves a remaining question: what is the *advantage*, why is it done? – Cheers and hth. - Alf Dec 02 '12 at 13:41
  • @Cheersandhth.-Alf - I've done my best to not get involved in locales. I recognize the code, but it's not mine. `` Seems to me this is about type erasure, but I don't know the details. – Pete Becker Dec 02 '12 at 16:30
1

Undefined doesn't mean it won't work, it just mean that an implementation is free to do whatever it wants, including working okay.

One possible problem with deleting the cast pointer is that the destructor may not be called but this may not be a problem if the type is one that doesn't have a constructor that needs to be reversed on deletion.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953