ios - Possible bug in libc++ for mac os ,string destructor is not called when string obj goes out of scope -
in libc++
have found basic_string destructor
not gets called , once string goes out of scope memory freed calling delete operator rather calling destructor
, calling delete operator destructor
, why so?
can 1 explain this? see sample program
void * operator new ( size_t len ) throw ( std::bad_alloc ) { void * mem = malloc( len ); if ( (mem == 0) && (len != 0) ) throw std::bad_alloc(); return mem; } void operator delete ( void * ptr ) throw() { if ( ptr != 0 ) free( ptr ); } int main(int argc, const char * argv[]) { std::string mystr("testing very big string string class"); std::string mystr2(mystr1.begin(),mystr.end()); }
put break point on new , delete , check call stack. new operator gets called basic_string class while delete gets called end of main, while ideally basic_string destructor
should have called first , delete operator should called via deallocate
call of allocator
, valid 2nd string creation.
i'm seeing same thing in debugger are; don't know sure, suspect stuff getting inlined. destructor basic_string
small; single test (for small string optimization), , call allocator's deallocate
function (through allocate_traits
). std::allocator
s allocate function quite small, wrapper around operator delete
.
you test writing own allocator. (later: see below)
more stuff generated while investigating question; read on if you're interested.
[note: there's bug in code - in second line wrote: mystr1.begin(),mystr.end())
- mystr1
declared?]
assuming that's typo, tried different code:
#include <string> #include <new> #include <iostream> int news = 0; int dels = 0; void * operator new ( size_t len ) throw ( std::bad_alloc ) { void * mem = malloc( len ); if ( (mem == 0) && (len != 0) ) throw std::bad_alloc(); ++news; return mem; } void operator delete ( void * ptr ) throw() { ++dels; if ( ptr != 0 ) free( ptr ); } int main(int argc, const char * argv[]) { { std::string mystr("testing very big string string class"); std::string mystr2(mystr.begin(),mystr.end()); std::cout << "news = " << news << "; dels = " << dels << std::endl; } std::cout << "news = " << news << "; dels = " << dels << std::endl; }
if run code, prints (at least me):
news = 2; dels = 0 news = 2; dels = 2
which should.
if toss code compiler explorer, see both calls basic_string::~basic_string()
, expect. (well, see three of them, 1 of them in exception handling block, ends call _unwind_resume
).
later - code:
#include <string> #include <new> #include <iostream> int news = 0; int dels = 0; template <class t> class myallocator { public: typedef t value_type; myallocator() noexcept {} template <class u> myallocator(myallocator<u>) noexcept {} t* allocate(std::size_t n) { ++news; return static_cast<t*>(::operator new(n*sizeof(t))); } void deallocate(t* p, std::size_t) { ++dels; return ::operator delete(static_cast<void*>(p)); } friend bool operator==(myallocator, myallocator) {return true;} friend bool operator!=(myallocator, myallocator) {return false;} }; int main(int argc, const char * argv[]) { { typedef std::basic_string<char, std::char_traits<char>, myallocator<char>> s; s mystr("testing very big string string class"); s mystr2(mystr.begin(),mystr.end()); std::cout << "allocator news = " << news << "; allocator dels = " << dels << std::endl; } std::cout << "allocator news = " << news << "; allocator dels = " << dels << std::endl; }
prints:
allocator news = 2; allocator dels = 0 allocator news = 2; allocator dels = 2
which confirms allocator getting called.
Comments
Post a Comment