46 / 46 / 18
Регистрация: 25.10.2011
Сообщений: 183
1

Классы - ошибка в деструкторе

24.03.2013, 16:46. Показов 892. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
У меня сейчас такое "задание": опередить класс длинного целого числа (длинная арифметика), для сохранения которого необходимо использовать однонаправленный связной список. Конструктор создаёт всего-лишь первый элемент списка "Head" со значениями data = NULL, next = NULL. При чтении числа значения заносятся в конец списка.
В итоге данный деструктор выдаёт ошибку при удалении двух чисел в конце работы программы:
C++
1
2
3
4
5
6
7
8
9
10
11
LongNum::~LongNum()
{
        LongNum *temp1 = this->Head;
        LongNum *temp2;
        while ( temp1 != NULL )
        {
                temp2 = temp1;
                temp1 = temp1->next;
                free(temp2);
        }
}
Для выделении памяти использую malloc.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.03.2013, 16:46
Ответы с готовыми решениями:

Ошибка в деструкторе
есть базовый абстрактный класс и есть производный от него: #ifndef EMPLOY_H #define EMPLOY_H ...

Ошибка в деструкторе
Программа работает без ошибок и полный её код не выкладываю. Но при выходе из программы получаю вот...

Ошибка в деструкторе
Когда удаляю объект класса hotel, в деструкторе вызывается delete для поля этого объекта -...

Ошибка при работе delete в деструкторе
enum place { first = 1, second }; class Passanger { public: Passanger(); void Call(); ...

12
...
1859 / 1292 / 949
Регистрация: 12.02.2013
Сообщений: 2,121
24.03.2013, 19:21 2
Hunter13ua, код в принципе верен (правда можно было бы и 1-ой вспомогательной переменной воспользоваться, но это мелочи). Покажите весь класс.
0
46 / 46 / 18
Регистрация: 25.10.2011
Сообщений: 183
24.03.2013, 19:29  [ТС] 3
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//---------------------------------------------------------------------------
 
#pragma hdrstop
 
//---------------------------------------------------------------------------
 
#pragma argsused
#include <stdio.h>
#include <stdlib.h>
#include "LongNumbers.cpp"
int main(int argc, char* argv[])
{
        LongNum A; LongNum B;
        A.Readln(); B.Readln();
        A=B;
        A.Write(A.Head);
        printf("\n");
        system("pause");
        return 0;
}
//---------------------------------------------------------------------------
LongNumbers.cpp
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
//---------------------------------------------------------------------------
 
#pragma hdrstop
 
#include "LongNumbers.h"
#include <stdio.h>
#include <alloc.h>
#include <string.h>
 
#define max( a, b ) ( (a < b) ? a : b )
 
LongNum::LongNum()
{
        this->Head = (LongNum*) malloc(sizeof(LongNum));
        this->Head->data = NULL;
        this->Head->next = NULL;
}
 
LongNum::~LongNum()
{
        LongNum *temp1 = this->Head;
        LongNum *temp2;
        while ( temp1 != NULL )
        {
                temp2 = temp1;
                temp1 = temp1->next;
                free(temp2);
        }
}
 
void LongNum::add_list(char d)
{
        LongNum* temp1 = this->Head;
        LongNum* temp2 = (LongNum*) malloc(sizeof(LongNum));
        temp2->data = d;
        temp2->next = NULL;
        if ( this->Head == NULL )
                this->Head = temp2;
        else
        {
                while ( temp1->next != NULL)
                        temp1 = temp1->next;
                temp1->next = temp2;
        }
}
 
void LongNum::Readln()
{
        char * string = new char [255];
        gets(string);
        size_t len = strlen(string);
        for(int i=len-1; i>=0; i--)
        {
                this->add_list(string[i]);
        }
}
 
size_t LongNum::GetSize()
{
        size_t size = 0;
        LongNum *temp = this->Head;
        if ( temp != NULL )
                size++;
        while ( temp->next != NULL )
        {
                size++;
                temp = temp->next;
        }
        return size;
}
 
void LongNum::Write(LongNum *head)
{
        if ( head != NULL )
        {
                if ( head->next != NULL )
                        LongNum::Write(head->next);
                printf("%c",head->data);
        }
}
 
void LongNum::Normalize()
{
        LongNum *temp = this->Head;
        if ( this->Head != NULL )
                if ( (this->Head->next == NULL) && ( this->Head->data == '0' ) )
                {
                        this->~LongNum();
                        puts("Normalization completed. Number was empty. Deleted.");
                }
        LongNum *pos = NULL;
        while ( temp->next != NULL )
        {
                if ( (temp->next->data == '0') && (pos == NULL) )
                        pos = temp;
                if ( temp->next->data != '0' ) pos = NULL;
                temp = temp->next;
        }
        if ( pos != NULL )
        {
                temp = pos->next;
                pos->next = NULL;
                pos = temp;
        }
        while ( pos != NULL )
        {
                temp = pos;
                pos = pos->next;
                free(temp);
        }
        printf("Normalization done.\n");
}
 
bool LongNum::check()
{
        LongNum *temp = this->Head;
        bool flag = false;
        while (temp->next != NULL)
        {
                if (temp->data != '0') flag = true;
                temp = temp->next;
        }
        return flag;
}
 
void LongNum::operator=(LongNum *A)
{
        LongNum *temp1 = this->Head;
        LongNum *temp2;
        while ( temp1->next != NULL )
        {
                temp2 = temp1;
                temp1 = temp1->next;
                free(temp2);
        }
        if (temp1 != NULL)
                free(temp1);
        this->Head = NULL;
 
        temp1 = A->Head;
        while ( temp1 != NULL )
        {
                this->add_list(temp1->data);
        }
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

LongNumbers.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//---------------------------------------------------------------------------
 
#ifndef LongNumbersH
#define LongNumbersH
#include <stddef.h>
class LongNum {
        private:
                char data;
                LongNum *next;
                void add_list(char d);
        public:
                LongNum *Head;
                LongNum();
                ~LongNum();
                void Readln();
                size_t GetSize();
                void Write(LongNum *head);
                void Normalize();
                bool check();
                void operator=(LongNum *A);
};
//---------------------------------------------------------------------------
#endif
0
4055 / 3309 / 924
Регистрация: 25.03.2012
Сообщений: 12,451
Записей в блоге: 1
24.03.2013, 19:37 4
Цитата Сообщение от Hunter13ua Посмотреть сообщение
#include "LongNumbers.cpp"
убери это и больше никогда не инклюдь срр файлы
0
46 / 46 / 18
Регистрация: 25.10.2011
Сообщений: 183
24.03.2013, 19:46  [ТС] 5
Kuzia domovenok, а объяснить почему можно? Я же не в курсе дела
0
4055 / 3309 / 924
Регистрация: 25.03.2012
Сообщений: 12,451
Записей в блоге: 1
24.03.2013, 19:51 6
потому что в языке С++ раздельная компиляция. СРР Файлы не должны практически ничего знать друг о друге.
0
46 / 46 / 18
Регистрация: 25.10.2011
Сообщений: 183
24.03.2013, 19:55  [ТС] 7
Kuzia domovenok, понял. А если вбить весь код из LongNumbers.cpp ниже в заголовочный файл - будет существенная разница ?
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
24.03.2013, 19:55 8
Цитата Сообщение от Hunter13ua Посмотреть сообщение
C++
1
2
3
LongNum A; LongNum B;
A.Readln(); B.Readln();
A=B;
A и B ссылаются на одну и туже память, и на момент вызова деструктора А, объект В уже освободит память, а деструктор А освободит повторно - что и приводит к ошибке
0
4055 / 3309 / 924
Регистрация: 25.03.2012
Сообщений: 12,451
Записей в блоге: 1
24.03.2013, 19:59 9
Говоря простым языком,
#include команда препроцессора, которая говорит, что перед компиляцией срр файла в это место будет скопипащен текст из другого файла. Обычно это требуется для добавления заголовочных (.h) файлов в программу. Но это не значит, что всю программу следует инклюдить в один файл, а затем компилировать.

Раздельная компиляция, как я её понимаю, это такая штука, что после того, как cpp файл прошёл препроцессор, он может компилироваться вне зависимости от наличия или отсутствия других срр файлов. Прочие срр могли скомпилироваться с ошибками или вообще их не хватает - не важно. компилятор обрабатывает срр файлы по-одному и строит из них куски кода.

Затем эти куски кода связываются linkerом. И только при этом процессе уже складываются в единый экзе файл. Поэтому не надо делать это раньше времени.
1
46 / 46 / 18
Регистрация: 25.10.2011
Сообщений: 183
24.03.2013, 20:07  [ТС] 10
Jupiter, так я ведь переопределил оператор присваивания. Он удаляет старую память, создаёт новую и туда уже копирует значения из второго объекта. Разве ошибся ?

Добавлено через 3 минуты
Kuzia domovenok, понял, благодарю за разъяснение
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
24.03.2013, 20:29 11
Цитата Сообщение от Hunter13ua Посмотреть сообщение
так я ведь переопределил оператор присваивания. Он удаляет старую память, создаёт новую и туда уже копирует значения из второго объекта. Разве ошибся ?
вы определили свой оператор равно.
для переопределения параметр должен передаваться: по значению, по ссылке, по ссылке на константу(+ volatile опционально к последним двум вариантам)
0
46 / 46 / 18
Регистрация: 25.10.2011
Сообщений: 183
24.03.2013, 23:27  [ТС] 12
Окей, тогда будьте добры, помогите с операцией присваивания
Классы только начал изучать, соответственно и операции.
Попытался переписать нечто:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
LongNum & LongNum::operator=(LongNum *A)
{
        LongNum *temp1 = this->Head;
        LongNum *temp2;
        while ( temp1->next != NULL )
        {
                temp2 = temp1;
                temp1 = temp1->next;
                free(temp2);
        }
 
        this->Head = (LongNum*) malloc(sizeof(LongNum));
        this->Head->data = NULL;
        this->Head->next = NULL;
 
        temp2 = this->Head;
        temp1 = A->Head;
        while ( temp1 != NULL )
        {
                temp2->add_list(temp1->data);
                temp1 = temp1->next;
        }
}
Не работает(
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
25.03.2013, 00:00 13
Цитата Сообщение от Hunter13ua Посмотреть сообщение
LongNum & LongNum::operator=(LongNum *A)
C++
1
2
3
4
5
6
7
8
9
LongNum& LongNum::operator = (const LongNum& A)
{
    if (this != &A)
    {
    //копируем
    }
    
    return *this;
}
0
25.03.2013, 00:00
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.03.2013, 00:00
Помогаю со студенческими работами здесь

Ошибка в деструкторе или перегрузке оператора C++ ООП
#include &lt;iostream&gt; #include &lt;iomanip&gt; #include &lt;conio.h&gt; #include &lt;math.h&gt; #include...

Возникает ошибка при удалении динамического массива символов в деструкторе класса
Всем привет. Есть приватная переменная, указатель на строку wchar_t *pUAgent; В конструкторе...

При работе с free в деструкторе ошибка "Invalid address specified to RtlValidateHeap"
Доброго времени суток, господа эксперты и дамы эксперты. Объясните пожалуйста почему программа...

Ошибка в деструкторе
Всем привет. Пытаюсь написать что-то типа динамического массива строк, и все шло довольно хорошо...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru