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

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

Восстановить пароль Регистрация
 
Hunter13ua
46 / 46 / 5
Регистрация: 25.10.2011
Сообщений: 183
24.03.2013, 16:46     Классы - ошибка в деструкторе #1
У меня сейчас такое "задание": опередить класс длинного целого числа (длинная арифметика), для сохранения которого необходимо использовать однонаправленный связной список. Конструктор создаёт всего-лишь первый элемент списка "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.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
anmartex
...
 Аватар для anmartex
1700 / 1193 / 494
Регистрация: 12.02.2013
Сообщений: 1,978
24.03.2013, 19:21     Классы - ошибка в деструкторе #2
Hunter13ua, код в принципе верен (правда можно было бы и 1-ой вспомогательной переменной воспользоваться, но это мелочи). Покажите весь класс.
Hunter13ua
46 / 46 / 5
Регистрация: 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
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
24.03.2013, 19:37     Классы - ошибка в деструкторе #4
Цитата Сообщение от Hunter13ua Посмотреть сообщение
#include "LongNumbers.cpp"
убери это и больше никогда не инклюдь срр файлы
Hunter13ua
46 / 46 / 5
Регистрация: 25.10.2011
Сообщений: 183
24.03.2013, 19:46  [ТС]     Классы - ошибка в деструкторе #5
Kuzia domovenok, а объяснить почему можно? Я же не в курсе дела
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
24.03.2013, 19:51     Классы - ошибка в деструкторе #6
потому что в языке С++ раздельная компиляция. СРР Файлы не должны практически ничего знать друг о друге.
Hunter13ua
46 / 46 / 5
Регистрация: 25.10.2011
Сообщений: 183
24.03.2013, 19:55  [ТС]     Классы - ошибка в деструкторе #7
Kuzia domovenok, понял. А если вбить весь код из LongNumbers.cpp ниже в заголовочный файл - будет существенная разница ?
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
24.03.2013, 19:55     Классы - ошибка в деструкторе #8
Цитата Сообщение от Hunter13ua Посмотреть сообщение
C++
1
2
3
LongNum A; LongNum B;
A.Readln(); B.Readln();
A=B;
A и B ссылаются на одну и туже память, и на момент вызова деструктора А, объект В уже освободит память, а деструктор А освободит повторно - что и приводит к ошибке
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
24.03.2013, 19:59     Классы - ошибка в деструкторе #9
Говоря простым языком,
#include команда препроцессора, которая говорит, что перед компиляцией срр файла в это место будет скопипащен текст из другого файла. Обычно это требуется для добавления заголовочных (.h) файлов в программу. Но это не значит, что всю программу следует инклюдить в один файл, а затем компилировать.

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

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

Добавлено через 3 минуты
Kuzia domovenok, понял, благодарю за разъяснение
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
24.03.2013, 20:29     Классы - ошибка в деструкторе #11
Цитата Сообщение от Hunter13ua Посмотреть сообщение
так я ведь переопределил оператор присваивания. Он удаляет старую память, создаёт новую и туда уже копирует значения из второго объекта. Разве ошибся ?
вы определили свой оператор равно.
для переопределения параметр должен передаваться: по значению, по ссылке, по ссылке на константу(+ volatile опционально к последним двум вариантам)
Hunter13ua
46 / 46 / 5
Регистрация: 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;
        }
}
Не работает(
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.03.2013, 00:00     Классы - ошибка в деструкторе
Еще ссылки по теме:

Оператор delete в деструкторе C++
C++ Ошибка в деструкторе
Вылет программы на деструкторе C++

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

Или воспользуйтесь поиском по форуму:
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
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;
}
Yandex
Объявления
25.03.2013, 00:00     Классы - ошибка в деструкторе
Ответ Создать тему
Опции темы

Текущее время: 17:58. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru