Re[7]: delete this
От: Аноним  
Дата: 09.04.07 12:28
Оценка:
ПК>Для возвращаемого значения или других случаев, где нужно подчеркнуть передачу владения -- auto_ptr, для объекта, который никуда из данной области видимости "уплыть не должен" -- scoped_ptr, для объекта с разделяемым владением -- shared_ptr, для не владеющих ссылок на него -- weak_ptr и т.п. Если объект нельзя удалять "обычным" delete, жизнь в этом контексте становится сложнее.
Смею заметить, автопоинтер — сам по себе тоже объект
Re[8]: delete this
От: Павел Кузнецов  
Дата: 09.04.07 13:31
Оценка:
Здравствуйте, Аноним, Вы писали:

ПК>>Для возвращаемого значения или других случаев, где нужно подчеркнуть передачу владения -- auto_ptr, для объекта, который никуда из данной области видимости "уплыть не должен" -- scoped_ptr, для объекта с разделяемым владением -- shared_ptr, для не владеющих ссылок на него -- weak_ptr и т.п. Если объект нельзя удалять "обычным" delete, жизнь в этом контексте становится сложнее.


А>Смею заметить, автопоинтер — сам по себе тоже объект


Гм... Не вполне понял, к чему это... Можно мысль поподробней развернуть?
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[9]: delete this
От: Аноним  
Дата: 09.04.07 13:39
Оценка: :)
А>>Смею заметить, автопоинтер — сам по себе тоже объект
ПК>Гм... Не вполне понял, к чему это... Можно мысль поподробней развернуть?
Если функция вернет автопоинтер на объект, кто вызовет деструктор самого автопоинтера? От этого зависит то, кто вызовет delete на указатель внутренние структуры автопоинтера и на сам объект который внутри хранится.
Если уж юзать автопоинтеры то экспортируемая dll функция должна возвращать простой указатель на объект с Release()'ом, а вызывающий должен заключать этот полученный указатель в свой автопоинтер который в конце вызовет не delete на объект, а Release. Как это и делает микрософтовский _com_ptr_t.
Кстати такой автопоинтер изобретать не надо — такое легко сделать и при помощи бустовского shared_ptr.
Re[10]: delete this
От: Smal Россия  
Дата: 09.04.07 14:09
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>Смею заметить, автопоинтер — сам по себе тоже объект

ПК>>Гм... Не вполне понял, к чему это... Можно мысль поподробней развернуть?
А>Если функция вернет автопоинтер на объект, кто вызовет деструктор самого автопоинтера? От этого зависит то, кто вызовет delete на указатель внутренние структуры автопоинтера и на сам объект который внутри хранится.
В shared_ptr этой проблемы нет. Из какой бы dll не вызвали деструктор shared_ptr его объект и счетчик удалятся корректно.
С уважением, Александр
Re[11]: delete this
От: Аноним  
Дата: 09.04.07 14:38
Оценка:
S>В shared_ptr этой проблемы нет. Из какой бы dll не вызвали деструктор shared_ptr его объект и счетчик удалятся корректно.

1) Покажите пожалуйста место где это написано в документации по boost::shared_ptr?
2) Из какого фрагмента кода shared_ptr.hpp это следует?
Re[12]: delete this
От: demi США  
Дата: 09.04.07 14:49
Оценка:
Здравствуйте, Аноним, Вы писали:

S>>В shared_ptr этой проблемы нет. Из какой бы dll не вызвали деструктор shared_ptr его объект и счетчик удалятся корректно.


А>1) Покажите пожалуйста место где это написано в документации по boost::shared_ptr?

А>2) Из какого фрагмента кода shared_ptr.hpp это следует?

shared_ptr::pn::get_deleter(), виртуальная функция удалает тем delete каким был создан (хитро там намешано )
Не стыдно попасть в дерьмо, стыдно в нём остаться!
Re[13]: delete this
От: Аноним  
Дата: 09.04.07 14:59
Оценка:
D>shared_ptr::pn::get_deleter(), виртуальная функция удалает тем delete каким был создан (хитро там намешано )
Хм ну если так то тогда мона юзать shared_ptr
Но я всегда юзаю нормальный Release для инетрфейсов по одной можно сказать идеологической причине.
Интерфейс — это полностью абстрактный класс в котором не реализован ни один метод. Объявляя
class IBaseClass
{
public:
virtual ~IBaseClass(){};
};

Вы создаете класс с реализованным деструктором. То бишь нифига он уже не абстрактный. Кроме того этот деструктор очень сильно ограничивает выбор компиляторов которыми компиляются разные модули. Например VS/Делфи для разнгых модулей заюзать не получится. Да и сама микрософт неспроста пошла по пути virtual void Release() в своих комах.
Re[12]: delete this
От: Smal Россия  
Дата: 09.04.07 15:02
Оценка:
Здравствуйте, Аноним, Вы писали:

S>>В shared_ptr этой проблемы нет. Из какой бы dll не вызвали деструктор shared_ptr его объект и счетчик удалятся корректно.


А>1) Покажите пожалуйста место где это написано в документации по boost::shared_ptr?

Это следует из следующего абзаца (хотя, возможно есть более точное упоминание)

Custom deallocators allow a factory function returning a shared_ptr to insulate the user from its memory allocation strategy. Since the deallocator is not part of the type, changing the allocation strategy does not break source or binary compatibility, and does not require a client recompilation. For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object, and other variations allow a shared_ptr to be used as a wrapper for another smart pointer, easing interoperability.

(отсюда)

А>2) Из какого фрагмента кода shared_ptr.hpp это следует?

А по коду тоже можно посмотреть.
shared_ptr держит указателя на объект и класс-обёртку для счетчика (detail::shared_count).
detail::shared_count выделяет динамически память для счетчика и deleter-а (sp_counted_impl_p/sp_counted_impl_pd).
У sp_counted_impl_p/sp_counted_impl_pd есть виртуальный метод dispose (унаследованный от sp_counted_base),
который вызывает deleter для хранимого указателя. Т.к. все это скрыто за виртуальным указателем, то удаляется в dll,
которая выделила память (даже в случае, если deleter стандартный и просто вызывается boost::checked_delete(p)).
Сам sp_counted_impl_p/sp_counted_impl_pd удаляется через виртуальный метод destroy (делается delete this).
Так что все безопасно.
С уважением, Александр
Re[13]: delete this
От: Аноним  
Дата: 09.04.07 15:04
Оценка:
Ok, а как насчет случая когда модуля окажутся скомпиленными разными версиями буста у которого чтото изменилось со струкурой shared_ptr?
Re[14]: delete this
От: Smal Россия  
Дата: 09.04.07 15:05
Оценка:
Здравствуйте, Аноним, Вы писали:

D>>shared_ptr::pn::get_deleter(), виртуальная функция удалает тем delete каким был создан (хитро там намешано )

А>Хм ну если так то тогда мона юзать shared_ptr
А>Но я всегда юзаю нормальный Release для инетрфейсов по одной можно сказать идеологической причине.
А>Интерфейс — это полностью абстрактный класс в котором не реализован ни один метод. Объявляя

class IBaseClass
{
public:
   virtual ~IBaseClass() =0 {};
};



Тогда интерфейс останется абстрактным.
С уважением, Александр
Re[14]: delete this
От: Smal Россия  
Дата: 09.04.07 15:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ok, а как насчет случая когда модуля окажутся скомпиленными разными версиями буста у которого чтото изменилось со струкурой shared_ptr?

Да врядли что-то там в виртуальном интерфейсе изменится. Поэтому, все будет пучком.
С уважением, Александр
Re[10]: delete this
От: Павел Кузнецов  
Дата: 09.04.07 18:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>Смею заметить, автопоинтер — сам по себе тоже объект


ПК>>Гм... Не вполне понял, к чему это... Можно мысль поподробней развернуть?


А>Если функция вернет автопоинтер на объект, кто вызовет деструктор самого автопоинтера?


Допустим, вызывающий код в другом модуле (иначе ситуация, вообще, неинтересная).

А>От этого зависит то, кто вызовет delete на указатель внутренние структуры автопоинтера


Либо у "умного" указателя нет никаких внутренних структур, требующих delete (scoped_ptr, auto_ptr), либо об этом позаботились авторы "умного" указателя (shared_ptr, weak_ptr).

А>и на сам объект который внутри хранится.


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

А>Если уж юзать автопоинтеры то экспортируемая dll функция должна возвращать простой указатель на объект с Release()'ом, а вызывающий должен заключать этот полученный указатель в свой автопоинтер который в конце вызовет не delete на объект, а Release. Как это и делает микрософтовский _com_ptr_t.


Это совершенно другой use case. Там нужна возможность работы не только через границу модулей, но и с модулями, построенными несовместимыми компиляторами и даже написанными на других языках. Привносить все эти сложности, теряя в выразительности интерфейсов, в случае "нормальных", "монокомпиляторных" DLL я не вижу никакого смысла.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[17]: delete this
От: minorlogic Украина  
Дата: 09.04.07 20:10
Оценка:
// start =============== native.h ====================
class example
{
public:
    virtual ~example() = 0 {}
};

example* create_example();
// end =============== native.h ====================


// start =============== native.cpp ====================
#include"native.h"

#include <memory.h>
#include <stdlib.h>
#include <stdio.h>



static void* operator new (size_t s)
{
    printf("new from native module\n");
    return malloc(s);
}

static void operator delete (void* p)
{
    printf("delete from native module\n");
    return free(p);
}


class example2 : public example 
{
    int i;
};


example* create_example()
{
   return new example2;
}
// end =============== native.cpp ====================


// start =============== test2.cpp ====================
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>


#include"native.h"

static void* operator new (size_t s)
{
    printf("delete from user module\n");
    return malloc(s);
}

static void operator delete (void* p)
{
    printf("delete from user module\n");
    return free(p);
}


class example3 : public example 
{
    int i;
};



int main(int argc, char* argv[])
{
    example* e = create_example();
    delete e;


    example* e3 = new example3;
    delete e3;


    return 0;
}
// end =============== test2.cpp ====================



Еще раз повторяю , что используется для удаления менежер памяти , именно то который и создавал. А после эксперимента , уберите виртуальный деструктор.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[17]: delete this
От: kmiken Украина  
Дата: 10.04.07 08:30
Оценка: +1 -1
Здравствуйте, Аноним, Вы писали:


Давайте попытаемся разложить оператор delete на атомы.

1. вызов деструктора (не важно как через вирт. таблицу или на прямую)
2. освбождение памяти.

Но тут я не открыл америки.

Теперь рассмотрим методы реализации:

1. Клиент (тот кто вызывает delete p) формирует следующий код.

// вызов деструктора:
   p->CDummy::~CDummy();
// или 
   (p->*vtbl[destructor_index])();

// освобождение памяти.
   ::operator delete(p);


В этом случае проблемы с менеджерами памяти будут в любом случае (виртуальный деструктор у класса или нет).

2. в виртуальной таблице хранится ссылка не на __чистый__ деструктор класса а на некий шлюз вида:
CDummy::~CDummy_Aux()
{
   this->CDummy::~CDummy();
   ::operator delete(this);
}



И тогда код на стороне клиента дубет следующий:
   (p->*vtbl[destructor_index])();

Я не знаю что говорит стандарт по этому поводу, но знаю что MS пошел по второму пути.
И по этой причине первый тест прошел на ура. Т.е. используется правильный менеджер памяти (CRT library)

Что касается второго вашего теста, смесь разных компиляторов, то в этом случае можно говорить только об экспорте/импортирте интерфейсов. Т.к. экспорт/импорт классов (реализаций) это сугубо компиляторно зависимая вешь (декорация имен и т.д. и т.п.).

Вывод:
Виртуальный деструктор решает проблему использования нужного CRT при разрушении объекта. Но надо понимать, что в этом случае речь идет не об экспорте интерфейса а об экспорте класса. А это уже совсем другая песня, и проблема с освобождением объекта покажется цветочками.
Re[18]: delete this
От: Аноним  
Дата: 10.04.07 09:01
Оценка:
K>Теперь рассмотрим методы реализации:
Не надо смотреть методы реализации, если только вы не пишете свою реализацию. В остальных случаях надо читать документацию.
Re[17]: delete this
От: minorlogic Украина  
Дата: 10.04.07 09:43
Оценка: -1
Таким образом тест доказал что я прав ? Вы мой вариант теста запусти , поняли о чем речь идет ?

А то что не работает с борманом и почему это отдельная история, надо в отладку идти.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[18]: delete this
От: Аноним  
Дата: 10.04.07 12:59
Оценка:
M>Таким образом тест доказал что я прав ? Вы мой вариант теста запусти , поняли о чем речь идет ?
Речь идет о написании C++ — compliant кода, а не MSVC X on Windows Y — compliant

M>А то что не работает с борманом и почему это отдельная история, надо в отладку идти.

Не работает — значит не совместимо со всеми С++ компилерами.
Re[19]: delete this
От: minorlogic Украина  
Дата: 10.04.07 13:24
Оценка:
Здравствуйте, Аноним, Вы писали:

M>>Таким образом тест доказал что я прав ? Вы мой вариант теста запусти , поняли о чем речь идет ?

А>Речь идет о написании C++ — compliant кода, а не MSVC X on Windows Y — compliant

Вы поставили довольно четкую проблему (а именно удаление памяти соответствующим менеджером памяти). Я написал как ее решить, С++ СОВМЕСТИМО. Написал тест демонстрирующий мои тезисы. Запустите его на той платформе где хотите совместимости.


M>>А то что не работает с борманом и почему это отдельная история, надо в отладку идти.

А>Не работает — значит не совместимо со всеми С++ компилерами.

Еще раз повторяю, тот баг который вы обнаруживаете, скорее всего не связан с описанной проблемой и требует отдельного изучения.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[19]: delete this
От: minorlogic Украина  
Дата: 10.04.07 13:25
Оценка:
Да запустите вы мой тест на бормане.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[20]: delete this
От: Аноним  
Дата: 10.04.07 13:30
Оценка:
M>>>Таким образом тест доказал что я прав ? Вы мой вариант теста запусти , поняли о чем речь идет ?
А>>Речь идет о написании C++ — compliant кода, а не MSVC X on Windows Y — compliant

M>Вы поставили довольно четкую проблему (а именно удаление памяти соответствующим менеджером памяти). Я написал как ее решить, С++ СОВМЕСТИМО.

Вы написали как ее решить MSVC++ совместимо.

M>Написал тест демонстрирующий мои тезисы. Запустите его на той платформе где хотите совместимости.

Я запустил. Win/Builder C++ — а delete упало. virtual void Release(){delete this;} работает на ура. Тот же код MSVC работает в обоих случаях.


M>>>А то что не работает с борманом и почему это отдельная история, надо в отладку идти.

А>>Не работает — значит не совместимо со всеми С++ компилерами.
M>Еще раз повторяю, тот баг который вы обнаруживаете, скорее всего не связан с описанной проблемой и требует отдельного изучения.
Если такое решение требует отдельного изучения реализации таблицы виртуальных методов в каждом из компиляторов — извольте. Мне нужен С++ решение. А межде прочим способ реализации виртуальных методов (структура vtbl и прочее) стандартом С++ никак не определяется, потому любое решение основывющееся на этом — грязный хак.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.