Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
#1

Shared_str реализация - На выходе из деструктора падает программа - C++

12.08.2014, 21:07. Просмотров 708. Ответов 21
Метки нет (Все метки)

Решил реализовать shared_str

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class shared_ptrMy
{
    private:
        Storage *st;
 
 
    public:
        shared_ptrMy(){};
        shared_ptrMy(Object*);
        ~shared_ptrMy();
        shared_ptrMy& operator=(shared_ptrMy&);
};
 
shared_ptrMy::shared_ptrMy(Object *o){
    st = new Storage(o);
}
 
shared_ptrMy& shared_ptrMy::operator=(shared_ptrMy &o){
    st->Copy(o.st);
    st = o.st;
    Storage *a = st;
    return *this;
}
 
 
 
shared_ptrMy::~shared_ptrMy(){
        delete st;
        st = NULL;
}

для этого я создал класс контейнер store
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Storage
{
    public:
        Storage(Object *o){
            pObj = o;
            counter = 1;
        }
        ~Storage(){
 
            int &k = counter;
            --counter;
 
            if(counter == 0)
                delete pObj;
        }
 
       Object& getObject(){
            return *pObj;
        }
 
        void Copy(Storage *s){
            ++(s->counter);
        }
 
 
   // private:
        Object *pObj;
        int counter ;
при этом counter работает нормально. Но когда counter == 0 вызывается деструктор для object все удаляется и на выходе из деструктора падает программа. Подскажите, что это может быть
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
zss
Модератор
Эксперт С++
6248 / 5851 / 1891
Регистрация: 18.12.2011
Сообщений: 14,993
Завершенные тесты: 1
12.08.2014, 21:26     Shared_str реализация - На выходе из деструктора падает программа #2
Похоже, память под pObj не выделяется.
Кроме operator= нужен копиконструктор.
И конструктор по умолчанию тоже должен инициализировать указатель
(хотя бы нулем, тогда прежде, чем удалять проверьте его на нуль).
MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
12.08.2014, 21:33  [ТС]     Shared_str реализация - На выходе из деструктора падает программа #3
объект точно есть
копи конструктор

C++
1
2
3
4
shared_ptrMy::shared_ptrMy(shared_ptrMy &ptr){
        this->st->Copy(ptr.st);
        this->st = ptr.st;
}
DrOffset
6859 / 4070 / 927
Регистрация: 30.01.2014
Сообщений: 6,869
13.08.2014, 00:15     Shared_str реализация - На выходе из деструктора падает программа #4
Цитата Сообщение от MishaMoix Посмотреть сообщение
this->st
В этом конструкторе st еще ни на что не указывает. Разыменование мусорного указателя ведет к падению.
MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
13.08.2014, 16:10  [ТС]     Shared_str реализация - На выходе из деструктора падает программа #5
Дело не в этом. Выше я уже описал проблему
ForEveR
Модератор
Эксперт С++
7958 / 4720 / 319
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
13.08.2014, 16:23     Shared_str реализация - На выходе из деструктора падает программа #6
MishaMoix, Покажите пример использования.
DrOffset
6859 / 4070 / 927
Регистрация: 30.01.2014
Сообщений: 6,869
13.08.2014, 16:27     Shared_str реализация - На выходе из деструктора падает программа #7
Цитата Сообщение от MishaMoix Посмотреть сообщение
Дело не в этом. Выше я уже описал проблему
В этом в том числе. Ошибка там не одна.
Показывай весь код, чтобы можно было воспроизвести твою ситуацию.
Avazart
7066 / 5243 / 263
Регистрация: 10.12.2010
Сообщений: 23,070
Записей в блоге: 17
13.08.2014, 20:50     Shared_str реализация - На выходе из деструктора падает программа #8
Как минимум счетчик тоже должен быть указателем.
MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
14.08.2014, 16:31  [ТС]     Shared_str реализация - На выходе из деструктора падает программа #9
Главная

C++
1
2
3
4
5
6
7
8
9
10
11
12
#include "shared_std.h"
#include <iostream>
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    shared_ptrMy a(new Object());
    shared_ptrMy b;
        b = a;
        
    return 0;
}
h shared_std

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "Storage.h"
#include <iostream>
 
class shared_ptrMy
{
private:
    Storage *st;
 
 
public:
    shared_ptrMy(){};
    shared_ptrMy(shared_ptrMy&);
    shared_ptrMy(Object*);
    ~shared_ptrMy();
    shared_ptrMy& operator=(shared_ptrMy&);
};
cpp shared_std
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "shared_std.h"
 
shared_ptrMy::shared_ptrMy(Object *o){
    st = new Storage(o);
}
 
shared_ptrMy& shared_ptrMy::operator=(shared_ptrMy &o){
    st->Copy(o.st);
    st = o.st;
    return *this;
}
 
 
 
shared_ptrMy::~shared_ptrMy(){
        delete st;
}
 
shared_ptrMy::shared_ptrMy(shared_ptrMy &ptr){
    this->st->Copy(ptr.st);
    this->st = ptr.st;
}
Storage h (ну я решил не заморачиваться и сделал inline фн)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "Object.h"
#include <iostream>
 
class Storage
{
public:
    Storage(Object *o){
        pObj = o;
        counter = 1;
    }
    ~Storage(){
        
        std::cout << "destruct";
        --(this->counter);
 
        //bool j = (pObj == 0);
 
        if (this->counter == 0) 
            delete pObj;
    }
 
    Object& getObject(){
        return *pObj;
    }
 
    void Copy(Storage *s){
        ++(s->counter);
    }
 
 
    // private:
    Object *pObj;
    int counter;
};
Ну и собственно object h

C++
1
2
3
4
5
6
7
8
9
class Object
{
public:
    Object();
    ~Object();
private:
 
    int *arr;
};
object cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "Object.h"
 
Object::Object()
{
    arr = new int[10000];
    for (int i = 0; i<10000; ++i) arr[i] = i;
    int l = arr[70];
}
 
Object::~Object()
{
    delete[] arr;
}
DrOffset
6859 / 4070 / 927
Регистрация: 30.01.2014
Сообщений: 6,869
14.08.2014, 17:04     Shared_str реализация - На выходе из деструктора падает программа #10
MishaMoix, Откомментил что происходит:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main(int argc, char* argv[])
{
    // 0. Создается объект "а"
    shared_ptrMy a(new Object()); //1. внутри создается объект класса Storage, st указывает на него
    shared_ptrMy b; //2. создается объект "b" - внимание указатель st в нем неинициализирован!
    b = a; // 3. выполняется operator=
    // 4. у st объекта "b" вызывается метод Copy - это уже неверно, 
    // т.к. st в "b" не содержит правильного адреса
    // но в моем случае это прокатило и программа пошла дальше, 
    // хотя могло и уже здесь упасть (UB есть UB)
    // Далее выполняется присваивание значения st из "а" значению st из "b"
    // теперь у нас два объекта "a" и "b", которые указывают на один и тот же экземпляр класса Storage
    // Затем идут вызовы деструкторов, деструктор "b" освобождает память Storage
    // Деструктор "a" пытается еще раз освободить память Storage, но т.к.
    // она уже освобождена, то это приводит к падению  
 
    return 0;
}
Вывод - полностью пересмотреть подход. В таком виде это работать не будет.
MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
14.08.2014, 18:02  [ТС]     Shared_str реализация - На выходе из деструктора падает программа #11
Можно тогда полюбопытствовать, когда я вызываю деструктор (delete) st я же вызываю то что стоит в фн ~Storage() или не так.
DrOffset
6859 / 4070 / 927
Регистрация: 30.01.2014
Сообщений: 6,869
14.08.2014, 18:22     Shared_str реализация - На выходе из деструктора падает программа #12
Цитата Сообщение от MishaMoix Посмотреть сообщение
Можно тогда полюбопытствовать, когда я вызываю деструктор (delete) st я же вызываю то что стоит в фн ~Storage() или не так.
Да.

Добавлено через 13 минут
Только помимо этого еще происходит освобождение памяти, которую занимает Storage. Т.к. в двух объектах a и b указатель после работы operator= указывает на один и тот же экземпляр Storage, то и освободить память мы пытаемся два раза, один из деструктора b, второй раз из a. А этого делать нельзя.
MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
14.08.2014, 18:27  [ТС]     Shared_str реализация - На выходе из деструктора падает программа #13
Т.е. когда я вызвал (ну т.е. он сам вызвался по окончании main) его, по моему коду вызывается деструтор st, по его коду ничего не происходит (разве что вычитается единица) НО и еще в объекте st удаляется int counter (т.к. это не указатель и удаляется автоматом при удалении объекта)?
Avazart
7066 / 5243 / 263
Регистрация: 10.12.2010
Сообщений: 23,070
Записей в блоге: 17
14.08.2014, 18:29     Shared_str реализация - На выходе из деструктора падает программа #14
Проверяй счетчик потом только освобождай память.
MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
14.08.2014, 18:36  [ТС]     Shared_str реализация - На выходе из деструктора падает программа #15
Ну в общем проблема была решена тем что счетчик проверялся в shared_std
DrOffset
6859 / 4070 / 927
Регистрация: 30.01.2014
Сообщений: 6,869
14.08.2014, 18:37     Shared_str реализация - На выходе из деструктора падает программа #16
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от MishaMoix Посмотреть сообщение
НО и еще в объекте st удаляется int counter (т.к. это не указатель и удаляется автоматом при удалении объекта)?
После отработки деструктора Storage, данные которые он хранит перестают быть доступными для обращения (т.к. память под объект освобождена). Т.е. ты конечно сможешь к ним обратиться, и даже возможно получишь адекватный результат, но это неопределенное поведение (т.е. может быть что угодно, например падение или вернутся какие-то левые данные) и делать так нельзя. Т.е. да, счетчик будет уничтожен при первом вызове ~Storage().
Цитата Сообщение от Avazart Посмотреть сообщение
Проверяй счетчик потом только освобождай память.
Ему еще нужно что-то сделать с неинициализированными указателями на Storage, т.к. конструктор копирования и оператор присваивания неадекватно себя ведут при том коде, который сейчас есть.
Avazart
14.08.2014, 18:40
  #17

Не по теме:

И опять же возникает вопрос почему класс не шаблонный ?
Что за название такое "shared_ptrMy" ? что нельзя было обвернуть shared_ptr в свое пространство имен "My"?

MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
14.08.2014, 18:58  [ТС]     Shared_str реализация - На выходе из деструктора падает программа #18
Все спасибо. Т.е. при вызове деструктора мы говорим "окей комп, вот у меня объект, все переменные объекта мне не нужны забирай себе, а так же вызови деструкторы у др. объектов (которые объявлены через указатели)"

Добавлено через 38 секунд
Ну я не ставил себе цель делать это шаблонным или с правильным названием
DrOffset
6859 / 4070 / 927
Регистрация: 30.01.2014
Сообщений: 6,869
14.08.2014, 19:20     Shared_str реализация - На выходе из деструктора падает программа #19
MishaMoix, Если интересно, вот тебе небольшой пример:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
 
template <typename T>
class storage
{
public:
    explicit storage(T * p)
        : counter_(0), data_(p)
    { }
    ~storage()
    {
        delete data_;
    }
    void inc_ref()
    {
        ++counter_;
    }
    void dec_ref()
    {
        if(--counter_ == 0)
        {
            delete this;
        }
    }
 
private:
    storage & operator=(storage const &);
    storage(storage const &);
 
    size_t counter_;
    T *    data_;
};
 
namespace my
{
 
template <typename T>
class shared_ptr
{
public:
    shared_ptr()
        : st_(0)
    { }
 
    shared_ptr(T * p)
        : st_(0)
    {
        if(p != 0)
        {
            st_ = new(std::nothrow) storage<T>(p);
            if(st_ != 0)
            {
                st_->inc_ref();
            }
            else
            {
                delete p;
                throw std::bad_alloc();
            }
        }
    }
    shared_ptr(shared_ptr const & x)
        : st_(x.st_)
    {
        if(st_ != 0)
        {
            st_->inc_ref();
        }
    }
 
    ~shared_ptr()
    {
        if(st_ != 0)
        {
            st_->dec_ref();
        }
    }
 
    shared_ptr & operator=(shared_ptr const & x)
    {
        shared_ptr(x).swap(*this);
        return *this;
    }
 
    shared_ptr & operator=(T * x)
    {
        shared_ptr(x).swap(*this);
        return *this;
    }
 
    void swap(shared_ptr & x)
    {
        storage<T> * tmp = st_;
        st_ = x.st_;
        x.st_ = tmp;
    }
 
private:
    storage<T> * st_;
};
 
}
 
class Object
{
public:
    Object()  { std::cout << "Object()\n";  }
    ~Object() { std::cout << "~Object()\n";}
};
 
 
int main()
{
    my::shared_ptr<Object> a(new Object());
    my::shared_ptr<Object> b = a;
    my::shared_ptr<Object> c;
    c = b;
}

http://codepad.org/fXiO0PHo
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.08.2014, 19:41     Shared_str реализация - На выходе из деструктора падает программа
Еще ссылки по теме:

C++ Очередное деструктивное: при вызове деструктора все падает
Падает программа с opencv C++
Реализация конструкторов и деструктора C++
Неожиданно падает программа с библиотекой ffmpeg C++
C++ Почему работает программа при выходе за пределы массива?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
MishaMoix
0 / 0 / 0
Регистрация: 03.04.2012
Сообщений: 99
14.08.2014, 19:41  [ТС]     Shared_str реализация - На выходе из деструктора падает программа #20
Я только не понял как и для чего swap?
Yandex
Объявления
14.08.2014, 19:41     Shared_str реализация - На выходе из деструктора падает программа
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru