Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.87/15: Рейтинг темы: голосов - 15, средняя оценка - 4.87
0 / 0 / 0
Регистрация: 23.10.2018
Сообщений: 3
1

Ошибка при вызове деструктора (при вызове delete в деструкторе)

23.10.2018, 17:37. Показов 3102. Ответов 22
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Не могу найти ошибку, при вызове деструктора от класса, который был создан при помощи конструктора с параметром const String &, возникает ошибка - не работает delete[]. Остальные деструкторы для других классов работают нормально.

Код:
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <iostream>
 
using namespace std;
 
//------------------------------------------//
 
int strLen(char *str)
{
    int i = 0;
    for (; str[i] != 0; i++);
    return i;
}
 
void strCopy(char *to_str, char *from_str)
{
    int l = strLen(to_str);
    for (int i = 0; i < l; i++)
    {
        to_str[i] = from_str[i];
    }
    to_str[l] = '\0';
}
 
//------------------------------------------//
 
class String
{
private:
    char *data;
    int length;
public:
    String();
    String(char *);
    String(const String &);
    ~String();
    String& operator=(const String &);
    String& operator+=(const String &);
    friend String operator+(const String &, const String &);
    void getDataStr()
    {
        cout << data << endl;
    }
};
 
//------------------------------------------//
 
String::String()
{
    data = new char[1];
    data[0] = '\0';
    length = 1;
}
 
String::String(char *str)
{
    data = new char[strLen(str) + 1];
    strCopy(data, str);
    length = strLen(data);
}
 
String::String(const String &orig)
{
    data = new char[strLen(orig.data)];
    strCopy(data, orig.data);
    length = strLen(data);
}
 
String::~String()
{
    delete[] this->data;
    length = 0;
}
 
String& String::operator=(const String &orig)
{
    delete[] this->data;
    this->data = new char[strLen(orig.data) + 1];
    strCopy(this->data, orig.data);
    length = strLen(this->data);
    return *this;
}
 
String& String::operator+=(const String &orig)
{
    int size = strLen(this->data) + strLen(orig.data);
    char* tmp = new char[size + 1];
    int l = strLen(this->data);
    for (int i = 0; i < l; i++)
    {
        tmp[i] = this->data[i];
    }
    for (int j = 0, k = l; k < size; j++, k++)
    {
        tmp[k] = orig.data[j];
    }
    tmp[size] = '\0';
    delete[] this->data;
    this->data = tmp;
    length = strLen(this->data);
    return *this;
}
 
String operator+(const String &a, const String &b)
{
    int size = strLen(a.data) + strLen(b.data);
    char *tmp = new char[size + 1];
    for (int i = 0; i < a.length; i++)
    {
        tmp[i] = a.data[i];
    }
    for (int j = 0, k = a.length; k < size; j++, k++)
    {
        tmp[k] = b.data[j];
    }
    tmp[size] = '\0';
    return tmp;
}
 
//------------------------------------------//
 
int main()
{
    setlocale(LC_ALL, "rus");
    char* b = new char[10];
    for (int i = 0; i < 9; i++)
    {
        cin >> b[i];
    }
    b[9] = '\0';
    char* c = new char[10];
    for (int i = 0; i < 9; i++)
    {
        cin >> c[i];
    }
    c[9] = '\0';
    String q(c);
    String A;
    String B(b);
    String C(q);
 
    cout << endl << "/--------0---------/" << endl << endl;
 
    B.getDataStr();
    C.getDataStr();
 
    cout << endl << "/--------1---------/" << endl << endl;
 
    A = B;
    A.getDataStr();
 
    cout << endl << "/--------2---------/" << endl << endl;
 
    A = B + C;
    A.getDataStr();
 
    cout << endl << "/--------3---------/" << endl << endl;
 
    B += C;
    B.getDataStr();
 
    q.~String();
    A.~String();
    B.~String();
    C.~String();
 
    system("pause");
    return 0;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.10.2018, 17:37
Ответы с готовыми решениями:

При вызове деструктора в строке delete[] data выбрасывается исключение
вот как раз вопрос по этой теме. программа отрабатывает все команды и в конце при вызове...

Ошибка при вызове деструктора
Здравствуйте, помогите разобраться с проблемой, она довольно распространенная и на форуме куча...

Ошибка при вызове деструктора
Всем привет ! Есть класс class building { private: string *location_street;...

Ошибка при вызове деструктора
Не могу дописать лабу... Надо создать 4 класса, описать поля и методы. Выкладываю исходники: Самый...

22
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
24.10.2018, 00:56 2
Цитата Сообщение от marakesh Посмотреть сообщение
C++
1
2
3
4
    q.~String();
    A.~String();
    B.~String();
    C.~String();
Кто это вас так делать научил? Это неверно для автоматических объектов, уберите.
0
0 / 0 / 0
Регистрация: 23.10.2018
Сообщений: 3
24.10.2018, 17:05  [ТС] 3
Нас учил так делать семинарист. Эта программа может обойтись без деструкторов?
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
24.10.2018, 17:20 4
Цитата Сообщение от marakesh Посмотреть сообщение
Эта программа может обойтись без деструкторов?
вообще нет, в вашем случае вероятно да..
Цитата Сообщение от marakesh Посмотреть сообщение
strLen(orig.data) + 1
у вас же есть поле length
0
Неэпический
18099 / 10685 / 2061
Регистрация: 27.09.2012
Сообщений: 26,895
Записей в блоге: 1
24.10.2018, 17:41 5
Цитата Сообщение от marakesh Посмотреть сообщение
Нас учил так делать семинарист.
Что-то я сомневаюсь что он именно так учил делал.
Ну, либо шарлатан какой-то попался.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
24.10.2018, 17:47 6
Цитата Сообщение от marakesh Посмотреть сообщение
Эта программа может обойтись без деструкторов?
Да, для объектов созданных на стеке он вызовется автоматически как только выдете за пределы видимости.
1
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
24.10.2018, 18:10 7
Цитата Сообщение от marakesh Посмотреть сообщение
Эта программа может обойтись без деструкторов?
Деструкторы вызываются автоматически для автоматических объектов. Они поэтому и называются - автоматические.
Сами деструкторы нужны, конечно же. Но вот вызывать их явно вы не должны, о чем я вам выше и сказал.

Добавлено через 2 минуты
Собственно ошибка в том, что компилятор все равно будет генерировать код автоматического вызова деструктора для ваших объектов. Не смотря на ваш явный вызов. Отсюда получаем ошибку двойного освобождения памяти, которая у вас проявилась вот так
Цитата Сообщение от marakesh Посмотреть сообщение
ошибка - не работает delete[]
Добавлено через 1 минуту
Цитата Сообщение от marakesh Посмотреть сообщение
Нас учил так делать семинарист
Если он вас именно так учил, то с прискорбием можно заключить, что язык C++ он не знает.
С прискорбием для вас, конечно же. Вам же у него и дальше учиться, я так понимаю.
2
44 / 20 / 14
Регистрация: 23.10.2018
Сообщений: 103
24.10.2018, 18:21 8
Цитата Сообщение от aLarman Посмотреть сообщение
Да, для объектов созданных на стеке он вызовется автоматически как только выдете за пределы видимости.
можно использовать, например, std::unique_ptr
1
0 / 0 / 0
Регистрация: 23.10.2018
Сообщений: 3
24.10.2018, 21:33  [ТС] 9
Всем большое спасибо!
0
Вездепух
Эксперт CЭксперт С++
12761 / 6644 / 1788
Регистрация: 18.10.2014
Сообщений: 16,801
24.10.2018, 21:41 10
Цитата Сообщение от marakesh Посмотреть сообщение
C++
1
2
3
4
5
6
String::String()
{
  data = new char[1];
  data[0] = '\0';
  length = 1;
}
В дополнение к уже сказанному: почему здесь length вдруг получает значение 1?

Это, в частности, приведет в неправильной работе всех методов, которые используют значение length из сконструированного по умолчанию объекта.
0
Неэпический
18099 / 10685 / 2061
Регистрация: 27.09.2012
Сообщений: 26,895
Записей в блоге: 1
24.10.2018, 21:47 11
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void strCopy(char *to_str, char *from_str)
{
    int l = strLen(to_str);//Зачем Вы определяете длину строки, которую нужно заменить?
    for (int i = 0; i < l; i++)//так скопируются только столько символов, сколько было в строке назначения
    {
        to_str[i] = from_str[i];//а если в строке-источнике не хватит символов, то беда
    }
    to_str[l] = '\0';//Этот ноль там уже есть, Вы же переписали символы до l
}
 
//при таком подходе, строчки
    data = new char[strLen(str) + 1];//вообще неверны, т.к.
    strCopy(data, str);//data смотрит на неинициализированную память, в которой strCopy будет искать нолик
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
25.10.2018, 12:59 12
Цитата Сообщение от sty4ent Посмотреть сообщение
можно использовать, например, std::unique_ptr
Его нужно использовать если выделяете и создаете объект в куче, а не на стеке. И тогда его использование облегчит жизнь - на нужно будет вызывать удаление по указателю объекта самостоятельно(т.к у объекта unique_ptr так же будет автоматически вызван деструктор после выхода из зоны видимости, т.к этот объект на стеке.). И это скорее совет "нужно использовать", что в конечном итоге вовсе и не обязательно )

Добавлено через 2 минуты
Цитата Сообщение от Croessmah Посмотреть сообщение
C++
1
to_str[l] = '\0';//Этот ноль там уже есть, Вы же переписали символы до l
Кажется Вы заблуждаетесь(или ткните меня носом), strLen вернет длину не включая символа "конец строки"

Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от DrOffset Посмотреть сообщение
Деструкторы вызываются автоматически для автоматических объектов. Они поэтому и называются - автоматические.
в Плюсах есть автоматические объекты O_o ? не видел ничего подобного в стандарте

0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
25.10.2018, 13:01 13
aLarman,
C++
1
2
3
char str[] = { 'a', 'b', 'c', '\0' };
strLen(str) // вернет 3
std::cout << str[3]; // что получаем?)
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
25.10.2018, 13:04 14
Цитата Сообщение от aLarman Посмотреть сообщение
в Плюсах есть автоматические объекты ? не видел ничего подобного в стандарте
Начинается...
http://eel.is/c++draft/basic.stc#auto
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
25.10.2018, 13:07 15

Не по теме:

Что то не понимаю сути вопроса, как это что то доказывает или опровергает?
Вы цикл обойдите с конкретными цифрами и увидите в чем дело



Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от DrOffset Посмотреть сообщение
Это конечно прекрасно, но там нет и слова про "автоматические объекты", есть только про "автоматическая длительность хранения " (уж простите не могу точный перевод предоставить)

0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
25.10.2018, 13:10 16
Цитата Сообщение от aLarman Посмотреть сообщение
Это конечно прекрасно, но там нет и слова про "автоматические объекты"
Автоматические объекты = объекты с automatic storage duration.
Точно так же как статические объекты = объекты со static storage duration.

Т.е. когда говорят статические объекты - вас это не смущает, а с автоматическими вдруг накладка вышла?
Или у вас просто норма выработки по буквоедству на сегодня не выполнена?
Тогда спешу вас расстроить: я в этой теме не давал формальных определений, чтобы к ним можно было так придираться.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
25.10.2018, 13:12 17

Не по теме:

Цитата Сообщение от Croessmah Посмотреть сообщение
C++
1
to_str[l] = '\0';//Этот ноль там уже есть, Вы же переписали символы до l
Цитата Сообщение от aLarman Посмотреть сообщение
Кажется Вы заблуждаетесь(или ткните меня носом), strLen вернет длину не включая символа "конец строки"
Цитата Сообщение от Azazel-San Посмотреть сообщение
C++
1
std::cout << str[3]; // что получаем?)
Так и быть уточню, НЕ включая l переписаны символы



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

Не по теме:

Цитата Сообщение от DrOffset Посмотреть сообщение
Т.е. когда говорят статические объекты - вас это не смущает, а с автоматическими вдруг накладка вышла?
Или у вас просто норма выработки по буквоедству на сегодня не выполнена?
Тогда спешу вас расстроить: я в этой теме не давал формальных определений, чтобы к ним можно было так придираться.
Так не спорю, товарищ, а кто то запомнит это и будет утверждать что есть именно "автоматически объекты"
Нормы не выполняю, природное занудство, пардоньте :)

0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
25.10.2018, 13:13 18
Цитата Сообщение от aLarman Посмотреть сообщение
Так не спорю, товарищ, а кто то запомнит это и будет утверждать что есть именно "автоматически объекты"
И он будет прав. Вы ерундой занимаетесь.
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
25.10.2018, 13:35 19
aLarman,
Цитата Сообщение от Croessmah Посмотреть сообщение
C++
1
to_str[l] = '\0';//Этот ноль там уже есть, Вы же переписали символы до l
Цитата Сообщение от aLarman Посмотреть сообщение
Кажется Вы заблуждаетесь(или ткните меня носом), strLen вернет длину не включая символа "конец строки"
Вернет без, но именно в той строке(вернее после выхода из цикла) на позиции l в массиве to_str действительно уже будет записан '\0'. Зачем еще раз его туда писать?)

Добавлено через 13 минут
C++
1
2
3
4
5
6
7
8
9
10
11
void strCopy(char *to_str, char *from_str)
{
    // на вход на же приходит строка вида { 'a', 'b', 'c', '\0' }
    // с терминирующим нулем, ну т.е. не она сама, а только 
    // указатель на первый эл. ато еще и тут придирку найдут :)
    // но сути не меняет, в памяти она такая будет
 
    int l = strLen(to_str); // получаем длину == 3
    for (int i = 0; i < l; ++i) // в цикле переписали все до '\0' он остался 
    to_str[l] = '\0'; // итого не имеет смысла
}
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
25.10.2018, 13:36 20
Цитата Сообщение от aLarman Посмотреть сообщение
Так не спорю, товарищ, а кто то запомнит это и будет утверждать что есть именно "автоматически объекты"
Нормы не выполняю, природное занудство, пардоньте
А я вот свою не выполнил, так что вот вам аргументы:

В стандарте их тоже так называют периодически.

The destructor is invoked for each automatic object of class type constructed, but not yet destroyed, since the try block was entered.
http://eel.is/c++draft/except.ctor#2

After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X's direct non-variant non-static data members, the destructors for X's non-virtual direct base classes and, if X is the most derived class ([class.base.init]), its destructor calls the destructors for X's virtual base classes.
http://eel.is/c++draft/class.dtor#9

Потому что эти фразы синонимичны по принципу, указанному выше:
Цитата Сообщение от DrOffset Посмотреть сообщение
Автоматические объекты = объекты с automatic storage duration.
Статические объекты = объекты со static storage duration.
Локальные к потоку объекты = объекты с thread local storage duration.
Динамические объекты = объекты с dynamic storage duration.
0
25.10.2018, 13:36
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.10.2018, 13:36
Помогаю со студенческими работами здесь

Ошибка при вызове деструктора
Программа компилиться нормально,но после выполнения system(&quot;pause&quot;); выползает непонятное окно,и...

Ошибка при вызове деструктора
Добрый вечер! Почему при вызове деструктора вылетает ошибка после компиляции кода? #include...

Ошибка при вызове деструктора
Подскажите, что не так с этим деструктором? Просто выдает ошибку. Если его убираю то все идет норм....

Ошибка при вызове деструктора
По окончании программы выдает ошибку #include &lt;string.h&gt; #include &lt;iostream&gt; using namespace...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru