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

Ошибка при использовании delete[] C++

17.02.2019, 19:07. Показов 9097. Ответов 112
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. Я создал класс, где должен динамически выделить память, а потом в конце программы, с помощью деструктора, освободить выделений участок памяти. Проблема в том, что у меня почему то VS 2017 выдает ошибку (смотри скриншот) при использовании delete. Смотрел в Интернете, в других проблема появлялась, когда использовали delete вместо delete[] при удалении массива. Ранее подобной проблемы не было (хотя я тогда не использовав классы, вся программа была в main-e). Пожалуйста, помогите найти проблему.


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
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
 
#include <iostream>
#include <chrono>
#include <ctime>
#include <conio.h>
#include <iomanip>
 
using namespace std;
 
class timer_1
{
private:
    int i;
    int *array = new int[4];   // динамически выделяю память
 
public:
    timer_1() //Конструктор, просто показ. что он работает
    {
        cout << "Start" << endl;
    }
 
    void sth_function()  // Функция для заполнения массива
    {
        for (i = 0; i < 4; i++)
        {
            system("pause");
            array[i] = i + 2;
            cout << "---" << array[i] << endl;
        }
        cout << "I has done something" << endl;
    }
    ~timer_1() //Деструктор. тут я должен освободить память, выделенную под array
    {
        cout << "End" << endl;
        delete [] array;
 
    }
};
 
int main()
{
 
    timer_1 ob1;
    ob1.sth_function();
    ob1.~timer_1();
    _getch();
    return 0;
 
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.02.2019, 19:07
Ответы с готовыми решениями:

Ошибка при использовании delete
И снова здравствуйте! Пишу раз третий.Я уже готов убицца ап сцену изза этого delete.Я не понимаю...

Ошибка при использовании new[] / delete[]
Здравствуйте. Пишу учебную программу, моделирующую движение лифта (если кто учебник Дейтелов читал,...

Ошибка при использовании оператора delete в Visual Studio 2010
Изучаю указатели в C++. Есть следующий код: #include &lt;iostream&gt; #include &lt;locale&gt; using...

Утечки памяти при использовании new/delete для двумерных массивов
Добрый день. Суть в том, что есть несколько функций, получающих на вход и возвращающих двумерные...

112
1659 / 488 / 106
Регистрация: 17.05.2015
Сообщений: 1,497
18.02.2019, 00:01 41
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от rat0r Посмотреть сообщение
Мне вполне очевидно, что ты бредишь.
Я утверждаю, что после вызова delete,
либо по завершению области видимости имени автоматического объекта,
вся занимаемая ими память может быть законным образом перераспределена.

После уничтожения объекта он уже не может быть переиспользован.
Нечего больше переиспользовать.

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

Цитата Сообщение от rat0r Посмотреть сообщение
Не читала, но осуждаю уверена". Так и думал.
Если человек не предоставляет вам какую либо цитату из стандарта,
это не значит, что он его не читал.

К тому же, в моих тезисах нет места осуждению.

Что бы это понимать нужно уметь думать.

Цитата Сообщение от rat0r Посмотреть сообщение
Ничем не обоснованные фантазии.
Попробуйте опровергнуть.

Цитата Сообщение от rat0r Посмотреть сообщение
Сейчас бы послушать от не читавших как понимать то, что они даже не читали.
Не поняла эту фразу.

Цитата Сообщение от rat0r Посмотреть сообщение
An object is created by a definition, by a new-expression, when implicitly changing the active member of a union, or when a temporary object is created ([conv.rval], [class.temporary]).
И?

Цитата Сообщение от eva2326 Посмотреть сообщение
Эту тафталогию нужно понимать в самом обычном обывательском смысле.
Все, что делает объект "новым" - тупо запуск конструктора.
В остальном это тот же самый объект.
0
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
18.02.2019, 00:08 42
rat0r,
Как то не получается согласиться...
Когда вызван деструктор производного класса то производный считается просроченным, так?
Но при этом деструктор базового класса ещё не вызван, и, соответственно для полей которые пришли из базового лайфтайм еще не завершился... объекты производного типа это контейнер и базовых полей. И что получается, для полей, которые находились в производном классе лайфтайм истёк, а для полей которые пришли из базового класса - нет, так как деструктор базового ещё не вызван.

Но объект же у нас один. Как так получается, часть его полей просрочены а часть(которая пришла из базового) нет... Тоже не вяжется

eva2326,
Почему нельзя использовать? Вот, в деструкторе же пользуемся.
И из других потоков вызываем данные и это вроде как не противоречит стандарту.

По поводу примера с кодом где есть lock_guard - проблемы разные могут быть.
Кода мало. Там просто два лока и все и как оно относится к обсуждаемому я не понял

Сори, что не цитирую, с телефона не удобно
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
18.02.2019, 00:13 43
Цитата Сообщение от eva2326 Посмотреть сообщение
После уничтожения объекта он уже не может быть переиспользован.
"Переиспользование" это вообще не к объекту, а к storage, который объект занимает (занимал).
Цитата Сообщение от https://timsong-cpp.github.io/cppwp/n4659/basic.life#1.4
the storage which the object occupies is released, or is reused by an object that is not nested within o
Цитата Сообщение от eva2326 Посмотреть сообщение
Если человек не предоставляет вам какую либо цитату из стандарта,
это не значит, что он его не читал.
Согласен. А вот фразы типа "там что нибудь написано" значат.
Цитата Сообщение от eva2326 Посмотреть сообщение
Попробуйте опровергнуть.
"Уверен, в стандарте что-нибудь написано (что-нибудь такое, что опровергает)"

Цитата Сообщение от Undisputed Посмотреть сообщение
И что получается, для полей, которые находились в производном классе лайфтайм истёк,
Как это получается? Пока не вызовется их деструктор (если он нетривиальный), то их лайфтайм не истекает.
0
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
18.02.2019, 00:21 44
Цитата Сообщение от eva2326 Посмотреть сообщение
Если по некоторому адресу расположен объект некоторого типа,
и с течением времени тип этого объекта не изменился,
значит это тот же самый объект.
То есть
C++
1
2
3
4
5
6
7
8
9
void foo()
{
    Some * p1 = new Some();
    //...
    delete p1;
}
//...
foo();
foo();
если во втором вызове foo так совпало, что new-expression создал объект по тому же адресу, что и при первом вызове foo, то мы имеем дело с тем же объектом, что и в первом вызове?
Цитата Сообщение от eva2326 Посмотреть сообщение
Все, что делает объект "новым" - тупо запуск конструктора.
А если конструктор делегирующий, то создается несколько новых объектов?
1
зомбяк
1584 / 1218 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
18.02.2019, 00:34 45
Цитата Сообщение от eva2326 Посмотреть сообщение
то такое "создание нового объекта"?
Объект - сущность, возникающая после завершения исполнения конструктора и прекращающая существование в момент начала исполнения деструктора.

В процессе обоих действий (конструктора/деструктора) для внешнего кода это будут "процессы в области памяти, выделенной под объект", но не действия с самим объектом.
0
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
18.02.2019, 00:45 46
rat0r,
Ну да, не истекает) Я об этом и говорю)

Допустим есть базовый и производный класс
В производном есть одно поле и ещё одно пришло от базового
Эти оба поля являются полями обьекта производного класса
Когда завершается лайфтайм экземпляра производного класса то он по идее является просроченным, так?
Но тут проблема. Деструктор базового ещё не вызван.
Поле, которое пришло из базового ещё не просрочено
А объект сам просрочен
Получается частичная просроченность т.к конструктор базового ещё не вызван
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
18.02.2019, 00:47 47
Undisputed, это просто обратный порядок к конструированию. Порядок конструирования тоже не кажется логичным?
0
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
18.02.2019, 08:11 48
rat0r,
Порядок конструирования вроде логичный.
В деструкции выходит немного иначе
Объект создан когда конструктор завершился
Думаю было бы логичнее считать объект уничтоженным когда деструктор завершился
В таком случае вопросов в отношении логики бы не было)
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
18.02.2019, 12:13 49
Цитата Сообщение от Undisputed Посмотреть сообщение
Думаю было бы логичнее считать объект уничтоженным когда деструктор завершился
Тогда, как я уже говорил, порядок уничтожения не будет обратным к порядку создания.
0
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
18.02.2019, 12:44 50
rat0r,
Не ради спора, просто хочу понять, почему?

Вроде все будет.
1) отработает деструктор производного
2) отработает деструктор базового
3) lifetime завершен

оба деструктора относятся к одному и тому же объекту
несмотря на то что деструкторов здесь два (или может быть более), объект то у нас один
речь именно о его lifetime

деструкторы по сути такие же методы но вызываются неявно
вот приведу такой пример (имитация вызова деструкторов):
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
#include <iostream>
 
struct base
{
    int *baseP = new int[5];
    void baseDestructor()
    {
        std::cout << "baseDestructor\n";
        delete[] baseP;
    } 
};
 
struct derived : base
{
    int *derivedP = new int[10];
    
    void *operator new(std::size_t size) 
    { 
        return malloc(size);
    } 
    
    void operator delete(void *p) 
    { 
        derived *pObj = static_cast<derived *>(p);
        pObj->derivedDestructor();
        pObj->baseDestructor();
        free(p);
    } // end lifetime
    
    void derivedDestructor()
    {
        std::cout << "derivedDestructor\n";
        delete[] derivedP;
    }
};
 
int main()
{
    derived *d = new derived;
    delete d;
}
Ну вот и все нормально. Вызвали деструкторы в нужном порядке и поля уничтожились так как мы и хотели.
0
Фрилансер
3709 / 2082 / 567
Регистрация: 31.05.2009
Сообщений: 6,683
18.02.2019, 13:13 51
Цитата Сообщение от Undisputed Посмотреть сообщение
Думаю было бы логичнее считать объект уничтоженным когда деструктор завершился
Ваше упорство совершенно непонятно. Согласитесь, что объект может оказаться частично разрушенным с самого начала работы деструктора.
2
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
18.02.2019, 13:25 52

Не по теме:

Black Fregat,
А вы уверены, что речь об этом?


Суть в том что утверждается то что время жизни обьекта истекло, но при этом этим объектом можно пользоваться
без противоречий стандарту. Разговор об этом идёт а не о том что какие то ресурсы могут быть освобождены явно и что кто то к ним может после этого обратиться.
На эти же грабли можно наступить вообще без всяких деструкторов, в процедурном стиле.
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
18.02.2019, 13:29 53
Цитата Сообщение от Undisputed Посмотреть сообщение
1) отработает деструктор производного
2) отработает деструктор базового
Это не написано явно, поэтому я сначала удалил ответ.
Но в общем можно сказать что деструктор базового отрабатывает в конце деструктора производного, до выхода из него.
Поэтому получается что деструктор базового заканчивает работу раньше, чем деструктор производного. И lifetime базового окончился бы раньше lifetime производного, если бы lifetime заканчивался в конце работы деструктора, а не в начале.
1
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
18.02.2019, 13:51 54
rat0r,
Да, согласен. Если рассуждать в контексте лайфтайма, правильнее было бы разместить вызов базового деструктора в деструкторе производного.

Тем не менее, если перенести вызов базового деструктора в конец производного, с технической точки зрения все равно получим то же стандартный порядок разрушения

Добавлено через 4 минуты
Осталось выяснить что мешает здесь сказать что лайфтайм заканчивается после завершения деструктора?)

Добавлено через 17 секунд
Осталось выяснить что мешает здесь сказать что лайфтайм заканчивается после завершения деструктора?)
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
18.02.2019, 14:03 55
Undisputed, и что будет, если деструктор базового подобъекта или подобъекта-мембера бросит исключение? Считать его lifetime не законченным?
0
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
18.02.2019, 14:17 56
rat0r,
Почему нет?
Для конструкторов же это так.
Если исключение покидает конструктор, то лайфтайм обьекта не начинается (начинается если хотя бы 1 конструктор отработал полностью, это я про делегирующие конструкторы)

Добавлено через 1 минуту
При этом до исключения можно занять ресурсы а деструктор то не сработает
0
1659 / 488 / 106
Регистрация: 17.05.2015
Сообщений: 1,497
24.02.2019, 16:54 57
Цитата Сообщение от TRam_ Посмотреть сообщение
Объект - сущность, возникающая после завершения исполнения конструктора и прекращающая существование в момент начала исполнения деструктора.
Только с точки зрения высокоровневой логики))
С технической точки зрения это не так.

Хорошее (полное) определение объекта даёт Страуструп:

Объект — это область памяти. Объект имеет класс памяти, определяющий его время жизни. Смысл значения, обнаруженного в объекте, определяется типом имени, использованного для доступа к нему.
(ц)
Цитата Сообщение от TRam_ Посмотреть сообщение
В процессе обоих действий (конструктора/деструктора) для внешнего кода это будут "процессы в области памяти, выделенной под объект", но не действия с самим объектом.
Эм... вообще то, конструктор нужен для того, что бы проинициализировать память чем то осмысленным.
Если вам не нужно выполнять действия с памятью, то вам и конструктор тоже не нужен)
С деструктором - аналогично.

Добавлено через 6 минут
Цитата Сообщение от Croessmah Посмотреть сообщение
если во втором вызове foo так совпало, что new-expression создал объект по тому же адресу, что и при первом вызове foo, то мы имеем дело с тем же объектом, что и в первом вызове?
Да.
Цитата Сообщение от Croessmah Посмотреть сообщение
А если конструктор делегирующий, то создается несколько новых объектов?
Вы мне скажите)
Как это соотносится с вашей логикой.

Для меня все просто: конструктор вообще ничего не конструирует.
Правильнее было бы назвать его "инизиализатором".

Добавлено через 8 минут
Цитата Сообщение от rat0r Посмотреть сообщение
"Уверен, в стандарте что-нибудь написано (что-нибудь такое, что опровергает)
Вы ошибаетесь ))

Цитата Сообщение от rat0r Посмотреть сообщение
"Переиспользование" это вообще не к объекту, а к storage, который объект занимает (занимал).

Здесь захотелось сделать небольшую ремарку.


Пример №1

Вот здесь имеет место быть один и тот же объект:

C++
1
2
3
4
5
6
some obj;
 
...
 
obj.~some();
new(&obj) some(new_params);
1. Объект не был разрушен.
2. Тип объекта не изменился.

Технически, объект изменил своё состояние, и не более того.


Пример №2
Различные объекты:

C++
1
2
3
4
5
6
7
8
9
char storage[1024];
 
...
 
new(storage) foo(params);
 
...
 
new(storage) baz(params);
Несмотря на то, что в обоих случаях объекты располагаются в одном и том же storage,
это - различные объекты. Они различаются типами данных.

Уже нельзя сказать, что "объект просто изменил своё состояние".
Изменился сам "объект".

Добавлено через 32 минуты
Цитата Сообщение от Undisputed Посмотреть сообщение
Почему нельзя использовать? Вот, в деструкторе же пользуемся.
И из других потоков вызываем данные и это вроде как не противоречит стандарту.
Деструктор освобождает все захваченные ресурсы.

Например класс строки.
У него уже запустился деструктор.
И он уже освободил память, которая когда то содержала буквоки.

Вот как вы собираетесь пользоваться такой строкой?

Цитата Сообщение от Undisputed Посмотреть сообщение
По поводу примера с кодом где есть lock_guard - проблемы разные могут быть.
Считаете - это нормально?
Использовать объект, если это приводит к проблемам?

Цитата Сообщение от Undisputed Посмотреть сообщение
Кода мало. Там просто два лока и все и как оно относится к обсуждаемому я не понял
Что произойдёт, если один поток будет выводить боковки в консоль в тот самый момент,
когда другой поток сделает delete ?
1
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
24.02.2019, 17:26 58
Цитата Сообщение от eva2326 Посмотреть сообщение
Да.
ну лан
If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object...
0
1659 / 488 / 106
Регистрация: 17.05.2015
Сообщений: 1,497
24.02.2019, 17:46 59
Цитата Сообщение от Croessmah Посмотреть сообщение
ну лан
Зачем вы постите одно и тоже?

Цитата Сообщение от eva2326 Посмотреть сообщение
Что касается цитаты:
object will automatically refer to the new object
Эту тафталогию нужно понимать в самом обычном обывательском смысле.
Все, что делает объект "новым" - тупо запуск конструктора.
В остальном это тот же самый объект.
Технически, говорить, что на старом месте новый объект - уместно,
только если на старом месте теперь располагается объект другого типа.

Вот тогда это будет действительно новый объект,
а не тот же самый, которому просто гайки подкрутили:

C++
1
memcpy(&obj, &stamp, sizeof(stamp));
0
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
24.02.2019, 18:05 60
Цитата Сообщение от eva2326 Посмотреть сообщение
Технически, говорить, что на старом месте новый объект - уместно,
только если на старом месте теперь располагается объект другого типа.
Ясно. Когда Вы умрете, и по Вашему адресу будет жить другой человек - это будете Вы, просто с чуть подкрученными гайками.
0
24.02.2019, 18:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.02.2019, 18:05
Помогаю со студенческими работами здесь

Ошибка при delete[]
Не понимаю, почему при delete Y; выдает ошибку. Без этой строки код работает на ура. Надеюсь на...

Ошибка при вызове delete
Вот код // ConsoleApplication1.cpp: определяет точку входа для консольного приложения. // ...

Ошибка при освобождении памяти (delete)
Здравствуйте! Есть массив lines, созданный вот так : int *line = new int ; Потом, пытаюсь его...

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

Ошибка при Delete[] и удаление латинских букв
Задача без ипользования стандартных библиотек ввести размер строки и после этого строку, например ...

Ошибка при удалении массива с помощью delete
Изучаю C++ и у меня задание разбить текст неопределенной длинны на массив строк. Нацарапал класс...


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

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