[serialization] add_facet, VC7.1, and overloading operator new

Hi, I've been playing around with overloading global operator new and delete and came across a problem concerning facets with VC7.1 in debug mode. Internally facets are reference counted and destroyed in [locale0.cpp - locale::_Locimp::~_Locimp()] via a macro _DELETE_CRT [xdebug]. Now when _DEBUG is defined this macro will not call 'operator delete' directly. So any facets added to a locale using 'operator new' will not be freed with 'operator delete'. In my case this leads to an assertion in dbgheap.c. This is because the heap manager correctly recognizes that it was not responsible for the allocation. boost/archive/impl/basic_text_iprimitive.ipp: add_facet( std::locale::classic(), new codecvt_null<BOOST_DEDUCED_TYPENAME IStream::char_type> ) Minimal example is appended to the bottom of this post. As for a possible work around (read hack) you can use _NEW_CRT instead of new directly. A some what nicer hack^H^H^H^Hsolution may be to get add_facet to perform the actual facet allocation itself using _NEW_CRT instead of the caller. Chris Byrne //////////////////////////////////////////////////////////////////////////// #include <boost/archive/add_facet.hpp> #include <boost/archive/codecvt_null.hpp> #include <boost/shared_ptr.hpp> #include <stdlib.h> #include <malloc.h> using namespace boost; using namespace boost::archive; using namespace std; void* operator new(size_t size) { char* block = reinterpret_cast<char*>(malloc(size + 1)); return block + 1; } void operator delete(void* address) { if (!address) return; char* block = reinterpret_cast<char*>(address); free(block - 1); } int main() { shared_ptr<locale> p; p.reset( add_facet(locale::classic(), new codecvt_null<char>) // add_facet(locale::classic(), _NEW_CRT codecvt_null<char>) ); p.reset(); return 0; }

and what about all the new's in add_facet.hpp ? Robert Ramey Chris Byrne wrote:
Hi,
I've been playing around with overloading global operator new and delete and came across a problem concerning facets with VC7.1 in debug mode. Internally facets are reference counted and destroyed in [locale0.cpp - locale::_Locimp::~_Locimp()] via a macro _DELETE_CRT [xdebug]. Now when _DEBUG is defined this macro will not call 'operator delete' directly. So any facets added to a locale using 'operator new' will not be freed with 'operator delete'.
In my case this leads to an assertion in dbgheap.c. This is because the heap manager correctly recognizes that it was not responsible for the allocation.
boost/archive/impl/basic_text_iprimitive.ipp: add_facet( std::locale::classic(), new codecvt_null<BOOST_DEDUCED_TYPENAME IStream::char_type> )
Minimal example is appended to the bottom of this post. As for a possible work around (read hack) you can use _NEW_CRT instead of new directly. A some what nicer hack^H^H^H^Hsolution may be to get add_facet to perform the actual facet allocation itself using _NEW_CRT instead of the caller.
Chris Byrne
////////////////////////////////////////////////////////////////////////////
#include <boost/archive/add_facet.hpp> #include <boost/archive/codecvt_null.hpp> #include <boost/shared_ptr.hpp> #include <stdlib.h> #include <malloc.h>
using namespace boost; using namespace boost::archive; using namespace std;
void* operator new(size_t size) { char* block = reinterpret_cast<char*>(malloc(size + 1)); return block + 1; }
void operator delete(void* address) { if (!address) return; char* block = reinterpret_cast<char*>(address); free(block - 1); }
int main() { shared_ptr<locale> p; p.reset( add_facet(locale::classic(), new codecvt_null<char>) // add_facet(locale::classic(), _NEW_CRT codecvt_null<char>) ); p.reset(); return 0; }
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Robert Ramey wrote:
and what about all the new's in add_facet.hpp ?
AFAICT only the facet allocation is causing a problem. 'new std::locale' is not affected as shared_ptr calls 'operator delete' correctly.
Chris Byrne wrote:
Hi,
I've been playing around with overloading global operator new and delete and came across a problem concerning facets with VC7.1 in debug mode. Internally facets are reference counted and destroyed in [locale0.cpp - locale::_Locimp::~_Locimp()] via a macro _DELETE_CRT [xdebug]. Now when _DEBUG is defined this macro will not call 'operator delete' directly. So any facets added to a locale using 'operator new' will not be freed with 'operator delete'.
In my case this leads to an assertion in dbgheap.c. This is because the heap manager correctly recognizes that it was not responsible for the allocation.
boost/archive/impl/basic_text_iprimitive.ipp: add_facet( std::locale::classic(), new codecvt_null<BOOST_DEDUCED_TYPENAME IStream::char_type> )
Minimal example is appended to the bottom of this post. As for a possible work around (read hack) you can use _NEW_CRT instead of new directly. A some what nicer hack^H^H^H^Hsolution may be to get add_facet to perform the actual facet allocation itself using _NEW_CRT instead of the caller.
Chris Byrne
////////////////////////////////////////////////////////////////////////////
#include <boost/archive/add_facet.hpp> #include <boost/archive/codecvt_null.hpp> #include <boost/shared_ptr.hpp> #include <stdlib.h> #include <malloc.h>
using namespace boost; using namespace boost::archive; using namespace std;
void* operator new(size_t size) { char* block = reinterpret_cast<char*>(malloc(size + 1)); return block + 1; }
void operator delete(void* address) { if (!address) return; char* block = reinterpret_cast<char*>(address); free(block - 1); }
int main() { shared_ptr<locale> p; p.reset( add_facet(locale::classic(), new codecvt_null<char>) // add_facet(locale::classic(), _NEW_CRT codecvt_null<char>) ); p.reset(); return 0; }
participants (2)
-
Chris Byrne
-
Robert Ramey