неправильное выделение в c ++ как выделение памяти для char *

0

Я занимаюсь 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 не определено.
  • 0
    Я также должен указать на проблему проектирования, PointerString в том, чтобы PointerString наследовал символьный массив из String .
Показать ещё 7 комментариев
Теги:

1 ответ

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;

Для issue //1 вы не выделили достаточно места для строки. Вы забыли завершающую запись NULL.

Для проблемы //2 вы объединяетесь в m_text прежде чем он будет правильно 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 выполняет всю работу, которую вы сейчас выполняете, за исключением более безопасной и эффективной.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню