c++ - A strange stack overflow when to call destructor in Visual studio 2015 -


i write simple string class in cpp, when add new features bad happened. stack overflow when call object s3 destructor. spent hour fix it, did not find wrong code locially , grammer correct. ask friend recode me fix it, when recoded on mac. there no bad thing happened in program. really confused , need fix it, if there wrong codes in truth. if not, maybe should comment on issue visual studio 2015. :(

this mystlstring.h

class mystlstring { public:     // default constructor     mystlstring();                                        // constructs string count copies of character ch.      mystlstring(size_t count, char ch);           // convert char consequence mystlstring     mystlstring(const char *s);      // copy constructor      mystlstring(const mystlstring &s);      // destructor     ~mystlstring();       using size_type = size_t;            using chart = char;                         // character type     using value_type = char;                    // value_type     using reference = value_type;               // reference      using const_reference = const value_type&;  // const reference      // returns reference character @ specified location pos.     reference at(size_type pos); //  const_reference at(size_type pos) const;    // not know how convert reference const_reference when return       // returns reference first character     chart& front();     const chart& front() const;      // returns reference last character, equivalent operator[](size() - 1)     chart& back();     const chart& back() const;      // returns pointer underlying array serving character storage.     chart* data();     const chart* data() const;      // operator assignment overloaded     mystlstring& operator=(const mystlstring &s);      // operator [] overloaded     reference operator[](size_type pos);     const_reference operator[](size_type pos) const;  private:     char* data_;     int length_; }; 

this mystlstring.cpp

#include "mystlstring.h" #include <cstring> #include <iostream> #include <stdexcept>  // construct empty string(zero size , unspecified capacity). mystlstring::mystlstring():data_(nullptr), length_(0) {  }  // constructs string count copies of character ch. mystlstring::mystlstring(size_t count, char ch) {     length_ = count;     if (count == 0)     {            data_ = nullptr;         return;     }     else    // when count not 0     {         data_ = new char[length_];         (size_t = 0; < count; ++i)         {             data_[i] = ch;         }     }  }  // constructs string contents initialized  // copy of null-terminated character string pointed s. // length of string determined first null character.  mystlstring::mystlstring(const char *s) {     length_ = strlen(s);     if (length_ == 0)     {         data_ = nullptr;         return;     }     data_ = new char[length_];     strcpy(data_, s); }  // copy constructor.  // constructs string copy of contents of other. mystlstring::mystlstring(const mystlstring &s) {     if (s.data_ == nullptr)     {         length_ = 0;         data_ = nullptr;     }     else     {         length_ = strlen(s.data_);         data_ = new char[length_];         strcpy(data_, s.data_);     } }  // destructor // free data_ pointer memory mystlstring::~mystlstring() {     if (data_ != nullptr)     {         delete []data_;     }     std::cout << "length_ = " << length_ << std::endl;  // test }  // returns reference character @ specified location pos. // bounds checking performed, exception of type std::out_of_range thrown on invalid acess mystlstring::reference mystlstring::at(size_type pos) {     if (pos >= strlen(data_))     {         throw std::out_of_range("pos cross-border!\n");     }     return data_[pos]; }   // returns reference first character mystlstring::chart& mystlstring::front() {     if (data_ == nullptr)     {         throw std::out_of_range("string empty!\n");     }         return data_[0]; }  const mystlstring::chart& mystlstring::front() const {     return this->front(); }  // returns reference last character mystlstring::chart& mystlstring::back() {     if (data_ == nullptr)     {         throw std::out_of_range("string empty!\n");     }     return data_[0]; }  const mystlstring::chart& mystlstring::back() const {     return this->back(); }  // returns pointer underlying array serving character storage. // pointer such range[data(); data()+strlen(data_)] valid  // in correspond values stored in string mystlstring::chart* mystlstring::data()  {     if (data_ == nullptr)     {         throw std::out_of_range("string empty!\n");     }     return data_; }  const mystlstring::chart* mystlstring::data() const {     return this->data(); }  // operator= overloaded // replace contents copy of str. // if *this , str same object, function has no effect mystlstring& mystlstring::operator=(const mystlstring &s) {     // if *this , str same object, function return *this     if (this == &s)     {         return *this;     }     if (s.length_ == 0)     {         length_ = 0;         data_ = nullptr;         return *this;     }     char* temp = s.data_;   // copy *s.data_     delete data_;                       // free old memory     data_ = new char[s.length_];            // copy data data_ member     strcpy(data_, temp);     length_ = s.length_;     return *this;                       // return object }  // operator[] overloaded // returns reference character @ specified location pos.  // no bounds checking perfromed. mystlstring::reference mystlstring::operator[](size_type pos) {     return this->at(pos); }  mystlstring::const_reference mystlstring::operator[](size_type pos) const {     return this->operator[](pos); } 

this testmystlstring.cpp(ps: have delete other normal functions)

#include "mystlstring.h" #include <iostream>  using std::cout; using std::endl;  int main(void) {     // test constructor convert char consequence mystlstring     mystlstring s3("qwe");     return 0; } 

this pic when call destructor

enter image description here

this pic of stack information when call destructor

enter image description here

const mystlstring::chart& mystlstring::front() const {     return this->front(); } 

will result in infinite recursion, causing stack overflow. if want re-use implementaion of non-const version, have use:

const mystlstring::chart& mystlstring::front() const {     return const_cast<mystlstring*>(this)->front(); } 

make same change mystlstring::back() , mystlstring::data().


Comments