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

C++

Войти
Регистрация
Восстановить пароль
 
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
#1

Освобождение динамически созданных переменных (2-ого уровня) - C++

09.08.2014, 23:22. Просмотров 626. Ответов 6
Метки нет (Все метки)

И так, продолжу старую тему про динамику.

На этот раз есть вот что:
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <math.h>
 
using namespace std;
 
typedef enum { BOOL,INT,FLOAT,STR } vtr;
 
struct var
{
    vtr t;//тип переменной
    union
    {
        bool b;
        int i;
        float f;
        char *s;
    }d;//данные переменной
};
var *v;
var *vn;
 
int gi = 0;
bool a = false;
int b = 0;
int DelMas();
int AddVar(int);
int Convert(int);
int Otext(int);
int main (int argc, char* argv[])
{
    int r = 0;
    b = 1;
    v = new var[b]; // 1 элемент
    v[0].t = BOOL;
    v[0].d.b = true;
    a = true;
    while(a == true)
    {
        r = 0;
        cout << "Viberite deictvie" << endl << "1:Read variable" << endl << "2:Add variable" << endl << "3:Exit" << endl;
        cin >> r;
        switch(r)
        {
        case 1:
            {
                if(b > 0)
                {
                    for(int i=0;i<b;i++)
                    {
                        cout << "Num: " << i << "; Type: " << v[i].t << "; Data: ";
                        gi = Otext(i);
                    }
                }
                else
                    cout << "Base Clean, you must add variable" << endl;
            }
            break;
        case 2:
            {
                cout << "Put special number equalent of type variable:" << endl;
                cout << "0.Bool; 1.Int; 2.Float; 3.Char" << endl;
                cin >> gi;
                if((gi < 0)||(gi > 3))
                {
                    cout << "Error number of type" << endl;
                    break;
                }
                gi=AddVar(gi);
                if(gi==0)
                {
                    cout << "Error adding variable" << endl;
                    break;
                }
            }
            break;
        case 3:
            a = false;
            break;
        default:
            cout << "Unknown procedure" << endl;
        }
    }
    gi = DelMas();
    delete []v;
    cout << "Struct destroyed" << endl;
    getch();
    return 0;
}
int Convert(int fi)
{
    switch(v[fi].t)
    {
    case BOOL:
        vn[fi].d.b = v[fi].d.b;
        break;
    case INT:
        vn[fi].d.i = v[fi].d.i;
        break;
    case FLOAT:
        vn[fi].d.f = v[fi].d.f;
        break;
    case STR:
        //strcpy(vn[fi].d.s,v[fi].d.s);
        vn[fi].d.s = v[fi].d.s;
        //delete[] v[fi].d.s;
        break;
    default:
        cout << "Unknown type" << endl;
    }
    return 0;
}
int DelMas()
{
    if(b > 0)
    {
        for(int i=0;i<b;i++)
        {
            if(v[i].t == STR)
            {
                delete[] v[i].d.s;
            }
        }
    }
    return 0;
}
int AddVar(int ft)
{
    char buf[255]="";
    int fRi=0;
    if((ft < 0)||(ft > 3))
    {
        return 0;
    }
    else
    {
        vn = new var[b+1];
        switch(ft)
        {
        case 0:
            {
                vn[b].t = BOOL;
                cout << "Enter Number: 0 - False; 1 - True;" << endl;
                gi=0;
                cin >> gi;
                if((gi < 0)||(gi > 1))
                {
                    cout << "Error, allowed only 1 or 0" << endl;
                    break;
                }
                if(gi==0)
                    vn[b].d.b = false;
                if(gi==1)
                    vn[b].d.b = true;
                fRi=1;
            }
            break;
        case 1:
            {
                vn[b].t = INT;
                cout << "Enter Integer Number" << endl;
                cin >> vn[b].d.i;
                cout << "Integer: " << vn[b].d.i << endl;
                fRi=1;
            }
            break;
        case 2:
            {
                vn[b].t = FLOAT;
                cout << "Enter Float Number" << endl;
                cin >> vn[b].d.f;
                fRi=1;
            }
            break;
        case 3:
            {
                vn[b].t = STR;
                cout << "Enter Letters" << endl;
                cin >> buf;
                vn[b].d.s = new char[strlen(buf)+1];
                strcpy(vn[b].d.s,buf);
                //cout << "Result: " << vn[b].d.s << endl;
                fRi=1;
            }
            break;
        default:
            cout << "Unknown type" << endl;
        }
        cout << "Start convert.." << endl;
        if(fRi==1)
        {
            for(int j=0;j<b;j++)
            {
                vn[j].t = v[j].t;
                gi = Convert(j);
            }
            b++;
            delete []v;
            v = vn;
        }
        else
        {
            delete []vn;
        }
    }
    return fRi;
}
int Otext(int fi)
{
    switch(v[fi].t)
    {
    case BOOL:
        if(v[fi].d.b == false)
        {
            cout << "False" << endl;
        }
        else
        {
            cout << "True" << endl;
        }
        break;
    case INT:
        cout << v[fi].d.i << endl;
        break;
    case FLOAT:
        cout << v[fi].d.f << endl;
        break;
    case STR:
        cout << v[fi].d.s << endl;
        break;
    default:
        cout << "Unknown type" << endl;
    }
    return 0;
}
Как видно из кода, динамически создаётся структура (возможно не правильно выразился, но не суть) в main:
C++
1
v = new var[b];
Я назвал это "первым уровнем".
Далее при добавлении переменной приходится снова обращяться к оператору New:
C++
1
vn = new var[b+1];
Естественно перезаписываются прежние данные в новый экземпляр vn, а старый v - удаляется.
Если новая переменная является STR, то приходится вновь пользоваться new:
C++
1
vn[b].d.s = new char[strlen(buf)+1];
Это второй уровень. ( типа вложенная динамическая переменная в динамическую структуру... ололо )

Вопрос собственно в том как правильно пользоваться оператором delete[] в данном случае. Я предположил что тут:
C++
1
2
vn[fi].d.s = v[fi].d.s;
delete[] v[fi].d.s;
надо бы удалить старую переменную, однако если разкоментировать эту операцию удаления, то при добавлении более двух раз типа STR первая будет стираться.
В общем поправьте код кто может, и если не затруднит может объясните как было бы правильно (можно и ссылку дать, если где то уже объяснено).
Спасибо.
*Пс: В архиве собственно сам exe, но с закоментированной строкой "//delete[] v[fi].d.s;"
Вложения
Тип файла: rar 1-TestConsoleUnion.rar (10.3 Кб, 2 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.08.2014, 23:22     Освобождение динамически созданных переменных (2-ого уровня)
Посмотрите здесь:

Освобождение памяти динамически созданных объектов - C++
Подскажите, есть к примеру три класса: Class1, Class2, Class3. В Class2 имеется метод, в котором динамически создаю объекты класса...

Файловые операции 2-ого уровня сложности. - C++
Подскажите пожалуйста найти такую штуку: список файловых ошибок(не уверен что правильно называю даже). Например,...

Освобождение динамически выделенной памяти - Visual C++
ОС Windows инициировала точку останова в TimeDelay2.exe. Это может быть вызвано повреждением кучи и указывает на ошибку в TimeDelay2.exe...

Удаление динамически-созданных компонентов - C++ Builder
Использую класс, компонентами которого кроме всего прочего, являются StaticText и Edit, графическое изображение. Создаю экземпляр класса...

Покраска динамически созданных StringGrid - C++ Builder
Всем доброго времени суток. Кто может подсказать как можно покрасить занятые текстом ячейки и вывести при наведение на эту ячейку Hint с...

События динамически созданных объектов - C++ Builder
Доброго всем времени суток! Суть вопроса такова: я динамически в пользовательском классе создаю объект класса TTimer. Мне необходимо...

События динамически созданных объектов - C++ Builder
Всем привет :) Вопрос в том, как сделать отдельные события для каждой динамически созданной кнопки ? Пока получилось только для всех...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
КОП
348 / 280 / 86
Регистрация: 15.08.2010
Сообщений: 762
10.08.2014, 01:49     Освобождение динамически созданных переменных (2-ого уровня) #2
Если я правильно понял суть проблемы, то вы зачем-то хотите освободить ту память, где хранится само значение строки, хотя
C++
1
vn[fi].d.s = v[fi].d.s;
копирует лишь указатель, но не дублирует саму строку. В данном случае вообще нет необходимости в delete[].

А вообще, попробуйте использовать вместо массива вектор, тогда никаких мутных копирований массивов не будет.
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
10.08.2014, 05:35  [ТС]     Освобождение динамически созданных переменных (2-ого уровня) #3
Цитата Сообщение от КОП Посмотреть сообщение
В данном случае вообще нет необходимости в delete[].
Но ведь если исходить из логики того, что если переменная была создана через New, то и удалять её надо Delete. В моём случае мне кажется что если я не удалю, то будет утечка памяти.(кстати можно как нибудь проверить?)

Цитата Сообщение от КОП Посмотреть сообщение
попробуйте использовать вместо массива вектор
НЕ ПРЕДЛАГАТЬ !!! (у меня свой стиль, векторы я принципиально использовать не хочу)

Я тут подумал, а ведь новую переменную vn[fi].d.s я не создаю через new... значит и удалять старую не нужно, хотя если не удалить, то старая останется, что не очень хорошо, ведь доступа к ней не будет. (ну я так думаю, а рез нет доступа, то при функции очищения памяти, вызываемой в конце main я не смогу освободить память этой переменной, т.к. освободится уже новая vn (удаляться то будет конешно v, но ведь после создания переменной v = vn)

Честно говоря я в замешательстве...

Цитата Сообщение от КОП Посмотреть сообщение
копирует лишь указатель
значит мне надо создать через new новую vn[fi].d.s, потом скопировать само значение и удалить старую? Вообще стоит ли это сделать?

Добавлено через 54 минуты
И кстати, когда я сделаю ещё функцию изменения переменной, то мне точно надо будет иметь возможность удалять старые значения, а значит мне нужен не указатель, а реальное значение...
КОП
348 / 280 / 86
Регистрация: 15.08.2010
Сообщений: 762
10.08.2014, 15:19     Освобождение динамически созданных переменных (2-ого уровня) #4
Проверка утечки памяти с++, гугл, первый запрос.

Цитата Сообщение от Izual Посмотреть сообщение
Я тут подумал, а ведь новую переменную vn[fi].d.s я не создаю через new... значит и удалять старую не нужно
Вот на этом и нужно поставить точку в предложении. Кол-во new равно кол-ву delete. Никакой старой переменной не остается, она всегда будет одна, вы лишь копируете указатели на неё.

Цитата Сообщение от Izual Посмотреть сообщение
значит мне надо создать через new новую vn[fi].d.s, потом скопировать само значение и удалить старую? Вообще стоит ли это сделать?
Новую создавать не нужно, при работе со строками копируют как раз указатели, что вы и сделали.

Цитата Сообщение от Izual Посмотреть сообщение
И кстати, когда я сделаю ещё функцию изменения переменной, то мне точно надо будет иметь возможность удалять старые значения, а значит мне нужен не указатель, а реальное значение...
вот тогда и будете освобождать память, и для этого нужен именно указатель, а реальное значение никакой роли не играет.


И напоследок, прошу не кидаться камнями, переписал программу с использованием векторов. (Сделал это, т.к. сам пару дней назад открыл для себя векторы и не успел потренироваться) Как по мне, код стало гораздо легче читать и вероятность накосячить с той же памятью в разы меньше.

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

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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <vector>
using namespace std;
 
typedef enum { BOOL, INT, FLOAT, STR } vtr;
 
struct var
{
    vtr t;//тип переменной
    union
    {
        bool b;
        int i;
        float f;
        char *s;
    }d;//данные переменной
};
vector<var> v;
 
 
int gi = 0;
bool a = false;
int DelMas();
int AddVar(int);
int Otext(int);
int main(int argc, char* argv[])
{
    var tmp;
    tmp.t = BOOL;
    tmp.d.b = true;
    v.push_back(tmp); // 1 элемент
    
    a = true;
    while (a == true)
    {
        int r = 0;
        cout << "Viberite deictvie" << endl << "1:Read variable" << endl << "2:Add variable" << endl << "3:Exit" << endl;
        cin >> r;
        switch (r)
        {
        case 1:
        {
                  if (!v.empty())
                  {
                      for (int i = 0; i<v.size(); i++)
                      {
                          cout << "Num: " << i << "; Type: " << v[i].t << "; Data: ";
                          gi = Otext(i);
                      }
                  }
                  else
                      cout << "Base Clean, you must add variable" << endl;
        }
            break;
        case 2:
        {
                  cout << "Put special number equalent of type variable:" << endl;
                  cout << "0.Bool; 1.Int; 2.Float; 3.Char" << endl;
                  cin >> gi;
                  if ((gi < 0) || (gi > 3))
                  {
                      cout << "Error number of type" << endl;
                      break;
                  }
                  gi = AddVar(gi);
                  if (gi == 0)
                  {
                      cout << "Error adding variable" << endl;
                      break;
                  }
        }
            break;
        case 3:
            a = false;
            break;
        default:
            cout << "Unknown procedure" << endl;
        }
    }
    gi = DelMas();
    cout << "Struct destroyed" << endl;
    system("pause");
    return 0;
}
int DelMas()
{
    if (!v.empty())
    {
        for (int i = 0; i<v.size(); i++)
        {
            if (v[i].t == STR)
            {
                delete[] v[i].d.s;
            }
        }
    }
    return 0;
}
int AddVar(int ft)
{
    var temp;
    char buf[255] = "";
    int fRi = 0;
    if ((ft < 0) || (ft > 3))
    {
        return 0;
    }
    else
    {
        switch (ft)
        {
        case 0:
        {
                  temp.t = BOOL;
                  cout << "Enter Number: 0 - False; 1 - True;" << endl;
                  cin >> gi;
                  if ((gi < 0) || (gi > 1))
                  {
                      cout << "Error, allowed only 1 or 0" << endl;
                      break;
                  }
                  if (gi == 0)
                      temp.d.b = false;
                  if (gi == 1)
                      temp.d.b = true;
                  fRi = 1;
        }
            break;
        case 1:
        {
                  temp.t = INT;
                  cout << "Enter Integer Number" << endl;
                  cin >> temp.d.i;
                  cout << "Integer: " << temp.d.i << endl;
                  fRi = 1;
        }
            break;
        case 2:
        {
                  temp.t = FLOAT;
                  cout << "Enter Float Number" << endl;
                  cin >> temp.d.f;
                  fRi = 1;
        }
            break;
        case 3:
        {
                  temp.t = STR;
                  cout << "Enter Letters" << endl;
                  cin >> buf;
                  temp.d.s = new char[strlen(buf) + 1];
                  strcpy(temp.d.s, buf);
                  //cout << "Result: " << vn[b].d.s << endl;
                  fRi = 1;
        }
            break;
        default:
            cout << "Unknown type" << endl;
        }
        v.push_back(temp);
    }
    return fRi;
}
int Otext(int fi)
{
    switch (v[fi].t)
    {
    case BOOL:
        cout << std::boolalpha << v[fi].d.b << endl;
        break;
    case INT:
        cout << v[fi].d.i << endl;
        break;
    case FLOAT:
        cout << v[fi].d.f << endl;
        break;
    case STR:
        cout << v[fi].d.s << endl;
        break;
    default:
        cout << "Unknown type" << endl;
    }
    return 0;
}
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
10.08.2014, 17:43  [ТС]     Освобождение динамически созданных переменных (2-ого уровня) #5
Цитата Сообщение от КОП Посмотреть сообщение
а реальное значение никакой роли не играет.
Так мне же надо удалить реальное значение, оно же место занимает, а исходя из того как я понимаю, если я в последствии удалю "delete[] v[fi].d.s", то я удалю не само значение, а указатель. Так?
КОП
348 / 280 / 86
Регистрация: 15.08.2010
Сообщений: 762
10.08.2014, 17:47     Освобождение динамически созданных переменных (2-ого уровня) #6
Цитата Сообщение от Izual Посмотреть сообщение
удалю "delete[] v[fi].d.s", то я удалю не само значение, а указатель
указатель нельзя удалить, можно лишь освободить память, на которую он указывает, т.е. значение
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.08.2014, 18:35     Освобождение динамически созданных переменных (2-ого уровня)
Еще ссылки по теме:

Удаление динамически созданных TSpeedButton - C++ Builder
Имеется такой вот код, оптимизации 0, но сейчас не об этом. При попытке удалить массив из But, происходит ошибка. Project...

События динамически созданных компонентов - C++ Builder
В проекте динамически создаются компоненты TShape нажатием мыши на форме. Для компоненты необходимо обработать событие OnMouseDown,в...

События динамически созданных компонентов... - C++ Builder
Как создать обработчик события для динамически созданного визуального компонента? TForm *mF; mF = new TForm(Form1); mF-&gt;Parent=Form1;...

Удаление динамически созданных объектов - C++ Builder
Помогите плз. Пишу курсач по МИО. Вот ща работаю над интерфейсом. Я по нажатию кнопку создаю динамически объект edit. Хочу теперь при...

Поиск динамически созданных TabSheet - C++ Builder
Помогите пожалуйста. Есть TPageControl, на нем динамически созданы вкладки (количество может быть разное). На форме динамически...


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

Или воспользуйтесь поиском по форуму:
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
10.08.2014, 18:35  [ТС]     Освобождение динамически созданных переменных (2-ого уровня) #7
Цитата Сообщение от КОП Посмотреть сообщение
можно лишь освободить память, на которую он указывает, т.е. значение
Значит первый мною предложенный вариант будет правильно работать? (без delete[]) И значит что если мне надо будет удалить переменную, то указывая на delete[] v[fi].d.s удалится само значение(находящееся фиг знает где, куда как раз таки и указывает этот указатель)?
Ну в таком случае я спокоен, значит всё работает как надо.(без использования stl(векторов))
Yandex
Объявления
10.08.2014, 18:35     Освобождение динамически созданных переменных (2-ого уровня)
Ответ Создать тему
Опции темы

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