2014-12-07 79 views
0

我在练习C++。在C++中为分配内存错误分配异常*

我在两个版本中实现了String类。在第一个版本中,文本保存在一个数组中。在第二个版本中,文本保存在动态分配内存中。第一个版本继承 。

第一个版本工作正常。 在第二个版本中,在concat函数的第一行中,我得到一个错误的分配异常。

这是代码:

 #include<iostream> 
    #include<string> 
    using namespace std; 

    class String{ 

    protected: 
     enum{SIZE=256}; 
     void setLen(const int length) 
     { 
      m_len = length; 
     } 
    private: 
     int m_len; 
     char m_text [SIZE]; 

    public: 

     String() 
     { 
      m_len = 0; 
      strcpy_s (m_text, 1, ""); 
     } 
     String(const char* text) 
     { 
      m_len = strlen(text); 
      strcpy_s (m_text, strlen(text) + 1, text); 
     } 
     const char* get() const 
     { 
      return m_text; 
     } 
     virtual void set(char* text) 
     { 
      strcpy_s (m_text, strlen(text) + 1, text); 
     } 
     int getLen() const 
     { 
      return m_len; 
     } 
     virtual void concat(const String &s) 
     { 
      strcat_s(m_text, strlen(m_text) + strlen(s.get()) + 1, s.m_text); 
     } 
     bool equal(const String &s)const 
     { 
      return strcmp(s.m_text, m_text); 
     } 
     bool operator ==(const String &s)const 
     { 
      return strcmp(s.m_text, m_text); 
     } 
     virtual void print()const 
     { 
      cout<<m_text; 
     } 


    }; 

    class PointString :public String { 
     char* m_text; 
    public: 
     PointString() 
     { 
      setLen(0); 
      m_text = new char[1]; 
      strcpy_s(m_text, 1,""); 
     } 
     PointString(const char* text) 
     { 
      setLen(strlen(text)); 
      m_text = new char[strlen(text)+1]; 
      strcpy_s(m_text, strlen(text)+1 ,text); 
     } 
     void set(char* text) 
     { 
      delete [] m_text; 
      setLen(strlen(text)); 
      m_text = new char[strlen(text)+1]; 
     } 
     void concat(const String &s) 
     { 
      char *temp = new char[strlen(m_text) + strlen(s.get())]; 
      strcpy_s(temp, SIZE, m_text); 
      strcat_s(m_text,strlen(m_text) + strlen(s.get()) + 1, s.get()); 
      delete [] m_text; 
      m_text = temp; 
     } 
     void print()const 
     { 
      cout<<m_text<<endl; 
     } 
    }; 

void main() 
{ 
    PointString str("1234"); 
    str.print(); 
    str.concat("8901"); 
    str.print(); 
    system("pause"); 
} 
+3

您将'm_text'初始化为'new char []',但是您不一定会在数组中放入''\ 0'(取决于使用哪个构造函数)。如果没有空终止符,'strlen'的行为是不确定的。 – dlf 2014-12-07 01:40:58

+0

我还必须指出让'PointerString'从'String'继承字符数组的设计问题。 – 2014-12-07 01:42:15

+0

不相关,但'strcpy_s'是微软的,而不是标准的C++ – vsoftco 2014-12-07 01:42:58

回答

1

问题是这在您的通话concat

char *temp = new char[strlen(m_text) + strlen(s.get())]; // 1 
    strcpy_s(temp, SIZE, m_text); 
    strcat_s(m_text, strlen(m_text) + strlen(s.get()) + 1, s.get()); // 2 
    delete[] m_text; 
    m_text = temp; 

对于问题// 1,你没有为字符串分配足够的空间。您忘记了终止空条目。

对于问题// 2,在连接到m_text之前,它的大小正确。

使用标准的字符串函数,以下原因改变没有任何问题:

char *temp = new char[strlen(m_text) + strlen(s.get()) + 1]; 
    strcpy(temp, m_text); 
    strcat(temp, s.get()); 
    delete[] m_text; 
    m_text = temp; 

使用Microsoft安全字符串函数,你应该保存新的字符串的长度在一个变量并在每个呼叫时使用。指定SIZE似乎不正确。下面是我的什么作品:

void concat(const String &s) 
{ 
    size_t sz = strlen(m_text) + strlen(s.get()) + 1; 
    char *temp = new char[sz]; 
    strcpy_s(temp, sz, m_text); 
    strcat_s(temp, sz, s.get()); 
    delete[] m_text; 
    m_text = temp; 
} 

有你的代码的其他问题。一个是缺少析构函数,因此无论何时创建PointString,都会发生内存泄漏。另一个问题是,由于缺少用户定义的复制构造函数和赋值运算符,因此将PointString复制并分配给另一个PointString将无法​​正常工作。

请仔细阅读上述主题,因为字符串类不能复制自己几乎不值得使用(如果您打算使用它),由于内存泄漏,根本无法使用目前(没有析构函数)。

如果您将自己从“作业”阶段中删除,std::string类将完成您现在正在执行的所有工作,除了更安全和高效。