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

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 26, средняя оценка - 4.85
insideone
Модератор
Автор FAQ
3635 / 913 / 48
Регистрация: 10.01.2010
Сообщений: 2,460
#1

delete void* - C++

04.02.2010, 15:33. Просмотров 3266. Ответов 24
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass{
public:
    int i;
};
 
void main()
{
    MyClass* MyObj = new MyClass;
    MyObj->i = 10;
    void* VoidLink = MyObj;
    delete VoidLink; // освободится ли память?
    std::cout << MyObj->i; // уже не 10
}
Освободит ли память "delete VoidLink;"? Просто хочется выделить под удаление ресурсов отдельную функцию, однако выделенные ресурсы локальны и не видны...
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
novi4ok
550 / 503 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
04.02.2010, 15:38     delete void* #2
а ты уже попробовал? и что получается?
insideone
Модератор
Автор FAQ
3635 / 913 / 48
Регистрация: 10.01.2010
Сообщений: 2,460
04.02.2010, 15:42  [ТС]     delete void* #3
Ну я лично не шибко разбираюсь в освобождении памяти. Код выполняется без ошибок. Я не могу понять когда память освободилась верно, а когда нет. Но после delete объект уже не содержит корректные данные. С другой стороны чтобы освободить память наверное нужно знать сколько весит объект. Но может ли void* дать такую информацию я не понимаю...
novi4ok
550 / 503 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
04.02.2010, 15:54     delete void* #4
память, думаю, освобождается. интересно, вызывается ли деструктор при таком удалении? можешь туда MessageBox (NULL, "kuku", "kuku", MB_OK|MB_TASKMODAL); вставить и посмотреть, выпрыгнет ли? если выполнить в дибаггере, выдает ли сообщение об утечках памяти после завершения?

Добавлено через 2 минуты
да, сам экземпляр твоего объекта занимает sizeof (MyClass) байт памяти. но он может еще где-то память аллокировать, которая освобождается, например, в деструкторе. этот момент подробнее нужно изучить.
insideone
Модератор
Автор FAQ
3635 / 913 / 48
Регистрация: 10.01.2010
Сообщений: 2,460
04.02.2010, 16:01  [ТС]     delete void* #5
Да я и так всегда в дебаге сижу (MS VS 2008). Ошибок нет. Деструктор не вызвался Плохо это... значит так можно сгребать в мусор только объекты для которых не нужен деструктор. Однако ещё не факт. Осталось понять освобождается ли память...

Добавлено через 2 минуты
C++
1
2
    delete VoidLink;
    delete MyObj;
Если сделать так то дебаггер уже ругается. Останавливается в dbgdel.cpp на строчке
C++
1
2
             /* verify block type */
            _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
Правда я слабо понимаю что это значит. Видимо все таки void* освободил ресурсы и повторное их освобождение вызывает исключение.
Evg
Эксперт CАвтор FAQ
17305 / 5553 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
04.02.2010, 16:09     delete void* #6
Память освободится, поскольку для освобождения памяти требуется знать только адрес участка (а его размер при выделении спрятан где-то в таблицах и записан в момент вызова new). При этом код у тебя работает в первую очередь потому, что так расположены звёзды (а точнее потому, что так реализована система run-time поддержки). Деструктор вызывается для того типа, какой имеет параметр delete. В твоём случае параметр имеет тип void*, поэтому никакого деструктора вызываться не будет. Если написать "delete (MyClass*)VoidLink", то вызовется класса MyClass
insideone
Модератор
Автор FAQ
3635 / 913 / 48
Регистрация: 10.01.2010
Сообщений: 2,460
04.02.2010, 16:19  [ТС]     delete void* #7
Короче говоря для Windows я могу так писать без опасений? (В случае если деструктор объекта не важен)
Evg
Эксперт CАвтор FAQ
17305 / 5553 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
04.02.2010, 16:26     delete void* #8
Я не могу тебе ответить наверняка на твой вопрос, потому что всё это зависит от реализации run-time поддержки в конкретном компиляторе. Хрен его не знает, что там получается при множественном виртуальном наследовании и как там вообще делается каст от указателя на "средний" класс в цепочке с множественным виртуальным наследованием к указетлю на void*

Я просто не могу толком понять, зачем это тебе нужно?
insideone
Модератор
Автор FAQ
3635 / 913 / 48
Регистрация: 10.01.2010
Сообщений: 2,460
04.02.2010, 16:29  [ТС]     delete void* #9
Я просто хотел сделать прослойку выделения памяти которая собирала бы все созданные в функции указатели в массив void* а по завершению их удаляла. Впрочем я как всегда извращаюсь, но эксперементировать это интересно. По крайне мере без любопытсва человечество бы осталось в каменном веке) Думаю все же конкретно от этого я откажусь раз тут все так на удачу
Evg
Эксперт CАвтор FAQ
17305 / 5553 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
04.02.2010, 16:33     delete void* #10
Забудь на минуту про удаление памяти. Опишина словах или на конкретном примере, как у тебя внешне будет выглядеть выделение памяти. Т.е. сделали new, а потом ручками дописали указатель к списку? А что делать, если у нас в середине процедуры стоит return, или throw? И какой смысл всего этого деяния: просто поэкспериментировать или сделать что-то полезное? Если что-то полезное, то зачем такая полезность с ограничением, что не вызывается деструктор (т.е. 99% случаев попадает под ограничение)?
insideone
Модератор
Автор FAQ
3635 / 913 / 48
Регистрация: 10.01.2010
Сообщений: 2,460
04.02.2010, 16:40  [ТС]     delete void* #11
Забудь на минуту про удаление памяти. Опишина словах или на конкретном примере, как у тебя внешне будет выглядеть выделение памяти. Т.е. сделали new, а потом ручками дописали указатель к списку?
Пожалуй...
Ну у списка есть дестуктор, он освободит ресурсы там.
И какой смысл всего этого деяния: просто поэкспериментировать или сделать что-то полезное?
Полезность была бы в том что мне не пришлось бы следить за delete однако я понял что не выйдет (из за деструкторов). В принципе да, мне просто было интересно было разобраться в этом вопросе, теперь я немного лучше понимаю про удаление памяти благодаря вам В общем delete void* делать не стоит)
Evg
Эксперт CАвтор FAQ
17305 / 5553 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
04.02.2010, 16:46     delete void* #12
> Ну у списка есть дестуктор, он освободит ресурсы там

Ответ неверный. Собственно одно из стандартных заблуждений. Когда ты пишешь

C++
1
MyClass* MyObj = new MyClass;
то реально в этом месте делаются сразу два дейстия: выделение памяти и вызов конструктора. Конструктор память НЕ выделает, он только инициализирует поля. Т.е. этот код эквивалентен (по своей сути):

C++
1
2
MyClass* MyObj = (MyClass*) malloc (sizeof (MyClass));
MyObj->MyClass(); // условно обозначил вызов конструктора, как будто бы он есть процедура
Аналогично работает delete: сначала вызывается деструктор, а потом делается освобождение памяти. Чтобы вызвать деструктор, нужно знать тип, куда ссылается указатель (чтобы вызвать деструктор того класса, которым является объект). Чтобы освободить память, ничего кроме адреса знать не нужно, поскольку информация о размере выделенной памяти была записана в скрытых местах в момент вызова malloc'а
insideone
Модератор
Автор FAQ
3635 / 913 / 48
Регистрация: 10.01.2010
Сообщений: 2,460
04.02.2010, 16:53  [ТС]     delete void* #13
ну если бы были объекты для который не нужен деструктор то можно было бы сделать так?
oxotnik
1586 / 1063 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
04.02.2010, 16:56     delete void* #14
Цитата Сообщение от insideone Посмотреть сообщение
Я просто хотел сделать прослойку выделения памяти которая собирала бы все созданные в функции указатели в массив void* а по завершению их удаляла. Впрочем я как всегда извращаюсь, но эксперементировать это интересно. По крайне мере без любопытсва человечество бы осталось в каменном веке) Думаю все же конкретно от этого я откажусь раз тут все так на удачу
Для того что бы не заморачиваться с выделением/освобождением памяти есть std::auto_ptr
Что бы хранить массивы объектов есть куча контейнеров (для примера std::vector), при разрушении которого будут вызваны соотв. деструкторы объектов, помещенных в контейнер.
CheshireCat
Эксперт С++
2891 / 1240 / 78
Регистрация: 27.05.2008
Сообщений: 3,327
04.02.2010, 17:10     delete void* #15
insideone, вместо довольно бессмысленных таки экспериментов рекомендовал бы потратить свободное время более целесообразным (с моей точки зрения, конечно) образом: погуглить по именам авторов Элджер, Мейерс, Саттер, Александреску, Джосаттис (иногда пишут Джосьютис) и скачать и почитать их книги (ну или погуглить Alger, Mayers, Sutter, Josuttis, Alexandresku.....)
Evg
Эксперт CАвтор FAQ
17305 / 5553 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
04.02.2010, 17:13     delete void* #16
Цитата Сообщение от insideone Посмотреть сообщение
ну если бы были объекты для который не нужен деструктор то можно было бы сделать так?
В теории да, но ограничения для этого я писал выше. Т.е. 100% гарантии, что это будет работать, скорее всего нет
oxotnik
1586 / 1063 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
04.02.2010, 17:17     delete void* #17
вообще то в С++ приводить к void* это плохая практика... не для этого придумывалось ООП со своими наворотами.
novi4ok
550 / 503 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
04.02.2010, 17:36     delete void* #18
Цитата Сообщение от insideone Посмотреть сообщение
ну если бы были объекты для который не нужен деструктор то можно было бы сделать так?
тогда, наверное, стоит подумать, нужны ли такие объекты.

Добавлено через 3 минуты
Цитата Сообщение от oxotnik Посмотреть сообщение
Для того что бы не заморачиваться с выделением/освобождением памяти есть std::auto_ptr
Что бы хранить массивы объектов есть куча контейнеров (для примера std::vector), при разрушении которого будут вызваны соотв. деструкторы объектов, помещенных в контейнер.
если я правильно понял, то объекты - разных типов. т.е. опять же совать их в std::vector<void*> v ?
в деструкторе вектора удалится память только под вектор (под его четыре указателя, каквые составляют в большинстве реализаций сам вектор). а сами объекты, на которые указывали эти указатели, будут ждать освобождения памяти, выделенной под приложение.
oxotnik
1586 / 1063 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
04.02.2010, 17:47     delete void* #19
Цитата Сообщение от novi4ok Посмотреть сообщение
если я правильно понял, то объекты - разных типов. т.е. опять же совать их в std::vector v ? в деструкторе вектора удалится память только четырех указателей, каквые составляют в большинстве реализаций сам вектор. а сами объекты, на которые указывали эти указатели, будут ждать освобождения памяти, выделенной под приложение.
если делать так:
Код
CSomeClass *pSomeClass = new CSomeClass();
vector <CSomeClass*>v;
v.push_back(pSomeClass);
то естественно само ниче не удалится
а для разных типов можно сделать базовый шаблон
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.02.2010, 18:30     delete void*
Еще ссылки по теме:

"delete [] a, b;" эквивалентно "delete [] a; delete [] b;"? C++
Чем отличается delete[] от delete? C++
Delete void* p = new classobject(); C++
C++ Builder Ошибка E2044 - operator delete must return void
Cannot convert from 'void (__thiscall CTest::* )(void)' to 'BYTE *' C++ WinAPI

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

Или воспользуйтесь поиском по форуму:
ISergey
Maniac
Эксперт С++
1346 / 879 / 51
Регистрация: 02.01.2009
Сообщений: 2,643
Записей в блоге: 1
04.02.2010, 18:30     delete void* #20
Можно такой фигни по навыдумывать..

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
#include <algorithm>
#include <iostream>
#include <vector>
 
 
class iref{
public:
    iref(iref* rhs):count(1) { vec.push_back(rhs); }
    virtual ~iref(){ count = 0; }
 
    virtual void release() { --count; if(!count)delete this; }  
    virtual void add()     { ++count; }
    //.......
    static void clear_all(){
        for(std::vector<iref*>::iterator i = vec.begin(); 
            i != vec.end(); 
            ++i)
            (*i)->iref::release();
        vec.clear();
    }
protected:
    int count;
    static std::vector<iref*> vec;
};
 
std::vector<iref*> iref::vec;
 
class a: public iref{
public:
    a(): iref(this) { std::cout << "a(): iref()"  << std::endl; }
    virtual ~a(){ std::cout << "~a(): iref()" << std::endl; }
 
    virtual void release() {
        --count; 
        if(!count){
            vec.erase(std::find(vec.begin(), vec.end(), this));
            delete this;
        }  
    }
};
 
class b: public iref{
public:
    b(): iref(this) { std::cout << "b(): iref()"  << std::endl; }
    virtual ~b(){ std::cout << "~b(): iref()" << std::endl; }
 
    virtual void release() {
        --count; 
        if(!count){
            vec.erase(std::find(vec.begin(), vec.end(), this));
            delete this;
        }  
    }
};
 
int main(){
    std::vector<iref*> v;
 
    a *a1 = new a;
    a *a2 = new a;
    a *a3 = new a;
    b *b1 = new b;
 
    b1->release();
    a1->release();
 
    iref::clear_all();
 
    return 0;
}
http://codepad.org/W1dNHGl0
Yandex
Объявления
04.02.2010, 18:30     delete void*
Ответ Создать тему
Опции темы

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