Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Объекты и утечка памяти

4
24 февраля 2003 года
mike
3.7K / / 01.10.2002
Так выглядит начало объявления класса
Код:
class mString {
private:
    struct srep {
        char *s;
        int n;
    };
    srep *p;
public:
    mString();
    mString(char *);
    mString(mString &);
    mString(long);
    ~mString();
    mString& operator =(char *);
    mString& operator =(mString&);
    char& operator [](int);
...


Ниже приведен оператор, в котором происходит утечка памяти. Может кто-нибудь, кто посильнее меня разбирается в ООП, скажет, почему это происходит ??

Код:
mString& mString::operator +(mString& y) {
    char *buf = new char[strlen(p->s) + strlen(y.p->s) + 1];
    if ( !buf )
        return *this;
    strcpy(buf, p->s);
    strcat(buf, y.p->s);
    mString *result = new mString(buf);
    delete buf;
    return *result;
}

mString& mString::operator =(char *s) {
    if ( p->n > 1 ) {
        p->n--;
        p = new srep;
    }
    else if ( p->n == 1 )
    delete p->s;
    if (s) {
        p->s = new char[strlen(s) + 1];
    strcpy(p->s, s);
        p->n = 1;
    }
    else {
        p->s = new char[2];
    strcpy(p->s, "");
        p->n = 1;
    }
    return *this;
}


Утечка происходит в следующем случае:

 
Код:
str=str1+str2;
250
25 февраля 2003 года
Joker
1.4K / / 20.02.2000
А как ты заметил утечку ?
И как так точно нашел место ?
 
Код:
str=str1+str2;

(Может сам билдер хреново срабатывает)
450
25 февраля 2003 года
suffer
64 / / 20.03.2000
для корректного удаления массивов используй delete []buf, а не просто delete buf;
4
25 февраля 2003 года
mike
3.7K / / 01.10.2002
Цитата:
Originally posted by Joker
А как ты заметил утечку ?
И как так точно нашел место ?
 
Код:
str=str1+str2;

(Может сам билдер хреново срабатывает)



Нет, пробовалось еще и в GCC (Юниксовый компилятор)

А утечка видна в команде top (посмотреть список процессов).

3
25 февраля 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by mike
Так выглядит начало объявления класса
Код:
class mString {
private:
    struct srep {
        char *s;
        int n;
    };
    srep *p;
public:
    mString();
    mString(char *);
    mString(mString &);
    mString(long);
    ~mString();
    mString& operator =(char *);
    mString& operator =(mString&);
    char& operator [](int);
...


Ниже приведен оператор, в котором происходит утечка памяти. Может кто-нибудь, кто посильнее меня разбирается в ООП, скажет, почему это происходит ??

Код:
mString& mString::operator +(mString& y) {
    char *buf = new char[strlen(p->s) + strlen(y.p->s) + 1];
    if ( !buf )
        return *this;
    strcpy(buf, p->s);
    strcat(buf, y.p->s);
    mString *result = new mString(buf);
    delete buf;
    return *result;
}

mString& mString::operator =(char *s) {
    if ( p->n > 1 ) {
        p->n--;
        p = new srep;
    }
    else if ( p->n == 1 )
    delete p->s;
    if (s) {
        p->s = new char[strlen(s) + 1];
    strcpy(p->s, s);
        p->n = 1;
    }
    else {
        p->s = new char[2];
    strcpy(p->s, "");
        p->n = 1;
    }
    return *this;
}


Утечка происходит в следующем случае:

 
Код:
str=str1+str2;



Вглубь не вдавался, но на первый взгляд настораживают операторы new внутри перегруженных операторов "+" и "=".
Т.о. при "+" создается новый, видимо временный, объект mString:
mString *result = new mString(buf);
но он нигде не уничтожается, т.е. налицо утечка памяти.
Аналогично и в "=", если в деструкторе mString не учтено удаление объектов, на которые указывают *p и *s, то также будет наблюдаться утечка.

Думаю, в "+" положение можно исправить изменив динамическое создание (через new) экземпляра mString на статическое, т.е.
mString result(buf);
По правилам времени жизни объектов, до конца строки "str=str1+str2;" всё должно дожить.

А вот как высвобождать buf, через delete или delete[], в данном случае не имеет значения.

450
25 февраля 2003 года
suffer
64 / / 20.03.2000
А почему не имеет значения? Какие аргументы?
3
25 февраля 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by suffer
А почему не имеет значения? Какие аргументы?



По стандарту С++, действительно, при создании через new[], нужно и удалять через delete[].
Но современные компиляторы это дело отлавливают и понимают без посторонней помощи.

450
25 февраля 2003 года
suffer
64 / / 20.03.2000
Про современные компиляторы понятно. Просто я уже сталкивался с подобными вещами в C++ Builder 5, т.е. удалял массивы не через delete[], а через delete, в результате получая ошибки.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог