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?
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.