Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> основы ООП, выбрасывается ошибка(исключ как я поним) 
V
    Опции темы
fuckingniger
Дата 11.10.2010, 04:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



ошибка такова

user posted image

вот код:
m_string.h
Код

#ifndef M_STRING_H
#define M_STRING_H

#include <iostream>
using namespace std;
class m_string
{
    friend ostream& operator<<(ostream& out,const m_string& s);
public:
    m_string(char* ="");//конструктор пребразования
    ~m_string();
    m_string operator()(int);
private:
    int length;
    char* ptr;
};

#endif

m_string.cpp
Код

#include <iostream>
#include <cstring>
#include "m_string.h"
using namespace std;

ostream& operator<<(ostream& out,const m_string& s)
{
    for(int i=0;i<=s.length ;i++)
        out << s.ptr[i];
    return out;
}
m_string::m_string(char*s)//конструктор пребразования
{
    length=strlen(s);
    ptr=new char [length+1];
    strcpy(ptr,s);

}
m_string::~m_string()
{
    delete []ptr;
}
m_string m_string::operator()(int a)
{
    char *s = new char[length-a+1] ;
    strcpy(s,ptr+a);
    static m_string temp(s);
    return temp;

main
Код

#include <iostream>
#include "m_string.h"
using namespace std;
int main()
{
    m_string str("abcdef");
    cout << str;
    cout << str(2);
    return 0;
}


собственно вопрос вот в чём.Если в string.cpp поменять
Код

static m_string temp(s);
    return temp;

на
Код


return s;


то всё чудно работает - конструктор преобразования работает как надо ...

но всё так не понимаю почему так неправильно - объясните плз почему.
PM MAIL   Вверх
bsa
Дата 11.10.2010, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



статические переменные инициализируются при первом входе в их область видимости. Другими словами, в твоем случае она инициализируется при первом входе в метод operator(). Причем, возможно аж до того, как s будет выделена память.

Кстати, твой код вообще какой-то странный. У тебя утечка памяти. Чтобы ее не было, перепиши так:
Код
m_string m_string::operator()(int a)
{
    return m_string(ptr + a);
}


Код
m_string str("abcdef");
Этот код вызовет предупреждение, так как ты пользуешься некорректным преобразованием строкового литерала к неконстантному указателю. Чтобы предупреждения не было, конструктор m_string должен быть таким:
Код
m_string(const char *s = "")

Чтобы не было утечек памяти тебе необходимо так же реализовать конструктор копирования и оператор присваивания. Так как оператор присваивания лучше всего реализуется через метод swap (m_string(param).swap(*this); return *this;) - обмен содержимым двух объектов, то рекомендую сначала сделать его.
PM   Вверх
fuckingniger
Дата 11.10.2010, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



это тестовая программа просто ради конструктора преобразования(посмотреть с чем его едят) - поэтому и не написал конструкторы копии и прочее

а в чём утечка памяти то?

и всё таки очень интересно что значит этот BLOCK_TYPE......

у меня какая -то обще методическая ошибка как я понимаю..........

Добавлено через 7 минут и 52 секунды
Код

return m_string(ptr + a);


а как это работает? ни встречал пока такой формы
PM MAIL   Вверх
Crafty
Дата 11.10.2010, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 3.11.2008

Репутация: 12
Всего: 14



Цитата(fuckingniger @  11.10.2010,  15:38 Найти цитируемый пост)
а в чём утечка памяти то?

Вот тут
Код

 char *s = new char[length-a+1] ;
 вы выделяете память но не освобождаете.
PM MAIL   Вверх
fuckingniger
Дата 11.10.2010, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



аа...понял но эта ошибка не в утечке....
PM MAIL   Вверх
fuckingniger
Дата 11.10.2010, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



неужели никто не знает?!

Это сообщение отредактировал(а) fuckingniger - 11.10.2010, 16:13
PM MAIL   Вверх
bsa
Дата 11.10.2010, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



fuckingniger, я уже написал в чем ошибка. В том, что статическая переменная инициализируется чем-то непонятным, лежащим в s. Так как это происходит ДО выполнения тела функции, в которой она объявлена.
PM   Вверх
fuckingniger
Дата 11.10.2010, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



ну эта ошибка  меня убивает просто ...

переписал функцию operator+   как глобальную (как друг класса) чтоб можно было вызывать  в любом порядке

и опять та же ошибка хотя старую (operator() )я не вызываю

привожу код заново чтоб всё ясно было

m_string.h
Код

#ifndef M_STRING_H
#define M_STRING_H

#include <iostream>
using namespace std;
class m_string
{
    friend ostream& operator<<(ostream& out,const m_string& s);
    friend m_string operator+(m_string,m_string);
public:
    m_string(char* ="");//конструктор пребразования
    ~m_string();
    m_string operator()(int);
private:
    int length;
    char* ptr;
};

#endif

m_string.cpp
Код

#include <iostream>
#include <cstring>
#include "m_string.h"
using namespace std;

ostream& operator<<(ostream& out,const m_string& s)
{
    for(int i=0;i<=s.length ;i++)
        out << s.ptr[i];
    return out;
}
m_string::m_string(char*s)//конструктор пребразования
{
    length=strlen(s);
    ptr=new char [length+1];
    strcpy(ptr,s);

}
m_string::~m_string()
{
    delete []ptr;
}
m_string m_string::operator()(int a)
{
    char *s = new char[length-a+1] ;
    strcpy(s,ptr+a);
    static m_string temp(s);
    delete s;
    return temp;
    //return m_string(ptr+a);
}


m_string operator+(m_string str_1,m_string str_2)
{
    char* s=new char[str_2.length+str_1.length+1];
    strcpy(s,str_1.ptr);
    strcpy(s+str_1.length,str_2.ptr);
    return s;
}

main.cpp
Код

#include <iostream>
#include "m_string.h"
using namespace std;
int main()
{
    m_string str_1("a");
    m_string str_2("bc");
    cout << str_1+str_2;
    //cout << str_1+"!!!!!!!!!!";
    //cout << str_1(2);
    return 0;
}



ошибка та же самая...
user posted image

PM MAIL   Вверх
bsa
Дата 11.10.2010, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(fuckingniger @  11.10.2010,  15:38 Найти цитируемый пост)
а как это работает? ни встречал пока такой формы 

создается новый объект типа m_string путем вызова подходящего по параметрам конструктора. Можно даже писать:
Код
int a = int(10.0);


Добавлено через 1 минуту и 12 секунд

 ! 
bsa
fuckingniger, ты читать умеешь? Я уже давно объяснил в чем у тебя проблема!

PM   Вверх
fuckingniger
Дата 11.10.2010, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



ну я дебагом просто проходил и всё нормально инициализируется
PM MAIL   Вверх
djamshud
Дата 11.10.2010, 16:42 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 4
Всего: 39



Вы не сделали конструктор копирования. При этом может быть вы и не замечаете, но у вас создаются копии строк тут:
Код

return temp;

Компилятор сам делает конструктор копирования, просто присваивая поля объектов друг другу. Таким образом вы имеете несколько указателей на одну и ту же область данных и несколько раз ее освобождаете.

То, что без static работает, можно отнести на оптимизацию компилятора (или даже фичу языка - тут не возьмусь утверждать), когда он "проталкивает" возвращаемую переменную из функции наружу - со static, очевидно, так сделать нельзя - чтобы внешний код не повредил статичные данные функции.

Попробуйте сделать m_string& operator()(int).

Добавлено @ 16:42
bsa, вы не правы, по-моему. Бабах происходит из-за дабл фрии.

Добавлено через 7 минут и 1 секунду
fuckingniger,

>ну я дебагом просто проходил и всё нормально инициализируется 

Да там и без дебага понятно, что инициализируется нормально. static-данные инициализируеются не просто при входе в зону видимости, а когда до них черед выполнения доходит.

Это сообщение отредактировал(а) djamshud - 11.10.2010, 16:46


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
fuckingniger
Дата 11.10.2010, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



djamshud 

по ходу да ...ща попробую ...забыл что при возвращении по значению вызывается конструктор копии(хоть и узнал это часов 30 назад всего!)
PM MAIL   Вверх
djamshud
Дата 11.10.2010, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 4
Всего: 39



Да, с оптимизациями и фичами я прогнал.
Код

return s;

Тут просто указатель s преобразуется в один объект m_string, после чего благополучно уничтожится. Это все равно что сделать так:
Код

return m_string(s);

Тут как раз наглядно видно, как "протолкнется" объект. А так
Код

m_string tmp(s);
return tmp;

опять все сдохнет.

Это сообщение отредактировал(а) djamshud - 11.10.2010, 17:02


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
Crafty
Дата 11.10.2010, 17:01 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 3.11.2008

Репутация: 12
Всего: 14



Конструктор копий:
Код

m_string::m_string(const m_string& rhs)
{
  this->length = rhs.length;
  ptr = new char [length+1];
  strcpy(ptr,rhs.ptr);
}


Оператор+
Код

m_string operator+(const m_string &str_1, const m_string &str_2)
{
    char* s = new char[str_2.length+str_1.length+1];
    strcpy(s,str_1.ptr);
    strcat(s,str_2.ptr);
    m_string temp(s);
    delete [] s;
    return temp;
}


Теперь вроде работает.
PM MAIL   Вверх
fuckingniger
Дата 11.10.2010, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



Цитата(djamshud @  11.10.2010,  16:42 Найти цитируемый пост)
То, что без static работает, можно отнести на оптимизацию компилятора (или даже фичу языка - тут не возьмусь утверждать), когда он "проталкивает" возвращаемую переменную из функции наружу - со static, очевидно, так сделать нельзя - чтобы внешний код не повредил статичные данные функции.

не совсем понял эту фразу....А так спасибо большое - после  написания конструктора копии всё запахало как надо

Добавлено через 2 минуты и 31 секунду
Цитата(djamshud @  11.10.2010,  16:58 Найти цитируемый пост)
Выделить всёкод C++
1:
2:
    
m_string tmp(s);
return tmp;

опять все сдохнет.

сдохнет из=за того что конструктор присваивания по умолчанию просто скопирует указатели(они будут указывать на 1 динамически выделенную память?)
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0989 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.