delete this
От: BoberPlus  
Дата: 05.04.07 08:23
Оценка:
Простой вопрос — допустима ли такая конструкция ?

void Obj::release()
{
   delete this;
}
Re: delete this
От: Smal Россия  
Дата: 05.04.07 08:27
Оценка: +1
Здравствуйте, BoberPlus, Вы писали:

BP>Простой вопрос — допустима ли такая конструкция ?


BP>
BP>void Obj::release()
BP>{
BP>   delete this;
BP>}
BP>

Допустима. Только если ты после этого использовать объект больше не будешь
С уважением, Александр
Re: delete this
От: Sm0ke Россия ksi
Дата: 05.04.07 13:20
Оценка: 1 (1) +1 :)
Здравствуйте, BoberPlus, Вы писали:

BP>Простой вопрос — допустима ли такая конструкция ?


BP>
BP>void Obj::release()
BP>{
BP>   delete this;
BP>}
BP>


Одно условие уже назвали выше.
Добавлю, что объект должен быть создан динамически, т.е. с помощью new
Re[2]: delete this
От: BoberPlus  
Дата: 06.04.07 07:57
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>Здравствуйте, BoberPlus, Вы писали:


BP>>Простой вопрос — допустима ли такая конструкция ?


BP>>
BP>>void Obj::release()
BP>>{
BP>>   delete this;
BP>>}
BP>>


S>Одно условие уже назвали выше.

S>Добавлю, что объект должен быть создан динамически, т.е. с помощью new

Ясно.

Объекты создаются динамически (new) фабрикой, фабрика в одной dll, созданные объекты используются в другой. "delete obj" вызывать из другой dll я по понятным причинам не могу, поэтому решил так делать.
Re[3]: delete this
От: gid_vvp  
Дата: 06.04.07 09:04
Оценка: 1 (1) -1
BP>Объекты создаются динамически (new) фабрикой, фабрика в одной dll, созданные объекты используются в другой. "delete obj" вызывать из другой dll я по понятным причинам не могу, поэтому решил так делать.

В этом случае лучше чтоб фабрика возвращала умный указатель, который бы сам всё подчищал
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: delete this
От: Павел Кузнецов  
Дата: 07.04.07 01:18
Оценка: +3
Здравствуйте, gid_vvp, Вы писали:

BP>>Объекты создаются динамически (new) фабрикой, фабрика в одной dll, созданные объекты используются в другой. "delete obj" вызывать из другой dll я по понятным причинам не могу, поэтому решил так делать.


_>В этом случае лучше чтоб фабрика возвращала умный указатель, который бы сам всё подчищал


К сожалению, "умных" указателей нужно более одной разновидности, и дублировать их для каждого объекта не всегда удобно. Альтернативой, не закрывающей возможность использования разнообразных способов удаления объектов класса, "торчащего" из DLL, может быть снабжение его собственными operator new/delete, реализованными в этой же DLL.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: delete this
От: minorlogic Украина  
Дата: 08.04.07 07:21
Оценка:
Здравствуйте, BoberPlus, Вы писали:

BP>Ясно.


BP>Объекты создаются динамически (new) фабрикой, фабрика в одной dll, созданные объекты используются в другой. "delete obj" вызывать из другой dll я по понятным причинам не могу, поэтому решил так делать.


Используя виртуальный декструктор все проблемы уходят. Рекомендую попробовать.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[4]: delete this
От: LuciferMoscow Россия  
Дата: 08.04.07 09:27
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Используя виртуальный декструктор все проблемы уходят. Рекомендую попробовать.

Даже статическая линковка рантайма?
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[5]: delete this
От: minorlogic Украина  
Дата: 08.04.07 14:51
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

LM>Здравствуйте, minorlogic, Вы писали:


M>>Используя виртуальный декструктор все проблемы уходят. Рекомендую попробовать.

LM>Даже статическая линковка рантайма?

Не очень понял о чем это. Можно на примере ?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[6]: delete this
От: LuciferMoscow Россия  
Дата: 08.04.07 15:08
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>>>Используя виртуальный декструктор все проблемы уходят. Рекомендую попробовать.

LM>>Даже статическая линковка рантайма?
M>Не очень понял о чем это. Можно на примере ?
Примерно об этом http://rsdn.ru/article/cpp/stlproblem.xml
Автор(ы): Роман Хациев
Дата: 27.02.2002
Если вы пытались работать с экземплярами классов STL, передавая их в DLL, или получая оттуда, а потом бросили это занятие из-за непонятных ошибок, возникающих в вашей программе, то эта заметка для вас. Даже если видимых проблем в вашей программе нет, то все равно прочитайте эту заметку, чтобы знать что делать, когда они появятся :)
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[7]: delete this
От: minorlogic Украина  
Дата: 08.04.07 16:44
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

LM>Здравствуйте, minorlogic, Вы писали:


M>>>>Используя виртуальный декструктор все проблемы уходят. Рекомендую попробовать.

LM>>>Даже статическая линковка рантайма?
M>>Не очень понял о чем это. Можно на примере ?
LM>Примерно об этом http://rsdn.ru/article/cpp/stlproblem.xml
Автор(ы): Роман Хациев
Дата: 27.02.2002
Если вы пытались работать с экземплярами классов STL, передавая их в DLL, или получая оттуда, а потом бросили это занятие из-за непонятных ошибок, возникающих в вашей программе, то эта заметка для вас. Даже если видимых проблем в вашей программе нет, то все равно прочитайте эту заметку, чтобы знать что делать, когда они появятся :)


А при чем тут это ? Если деструктор виртуальный , он пользуется РОДНЫМ менеджером памяти , в этом то и смысл.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[8]: delete this
От: LuciferMoscow Россия  
Дата: 08.04.07 17:19
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>>>>>Используя виртуальный декструктор все проблемы уходят. Рекомендую попробовать.

LM>>>>Даже статическая линковка рантайма?
M>>>Не очень понял о чем это. Можно на примере ?
LM>>Примерно об этом http://rsdn.ru/article/cpp/stlproblem.xml
Автор(ы): Роман Хациев
Дата: 27.02.2002
Если вы пытались работать с экземплярами классов STL, передавая их в DLL, или получая оттуда, а потом бросили это занятие из-за непонятных ошибок, возникающих в вашей программе, то эта заметка для вас. Даже если видимых проблем в вашей программе нет, то все равно прочитайте эту заметку, чтобы знать что делать, когда они появятся :)

M>А при чем тут это ? Если деструктор виртуальный , он пользуется РОДНЫМ менеджером памяти , в этом то и смысл.
Кто-то это может подтвердить?
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[9]: delete this
От: minorlogic Украина  
Дата: 08.04.07 17:32
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

LM>Здравствуйте, minorlogic, Вы писали:


M>>>>>>Используя виртуальный декструктор все проблемы уходят. Рекомендую попробовать.

LM>>>>>Даже статическая линковка рантайма?
M>>>>Не очень понял о чем это. Можно на примере ?
LM>>>Примерно об этом http://rsdn.ru/article/cpp/stlproblem.xml
Автор(ы): Роман Хациев
Дата: 27.02.2002
Если вы пытались работать с экземплярами классов STL, передавая их в DLL, или получая оттуда, а потом бросили это занятие из-за непонятных ошибок, возникающих в вашей программе, то эта заметка для вас. Даже если видимых проблем в вашей программе нет, то все равно прочитайте эту заметку, чтобы знать что делать, когда они появятся :)

M>>А при чем тут это ? Если деструктор виртуальный , он пользуется РОДНЫМ менеджером памяти , в этом то и смысл.
LM>Кто-то это может подтвердить?

Например тест.
Стандарт.
Здравый смысл.

Деструкто то вызывается виртуальный через виртуальный вызов, и данной точке компилятор просто банально не знает размера удаляемого объекта. А знает его только в том модуле где перегружен деструктор для реального объекта.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[10]: delete this
От: LuciferMoscow Россия  
Дата: 08.04.07 17:36
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Например тест.

M>Стандарт.
M>Здравый смысл.
M>Деструкто то вызывается виртуальный через виртуальный вызов, и данной точке компилятор просто банально не знает размера удаляемого объекта. А знает его только в том модуле где перегружен деструктор для реального объекта.
там(статическая линковка) проблема совсем не в размере объекта и освобождение памяти вызывается ПОСЛЕ отработки ВСЕХ деструкторов
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[11]: delete this
От: minorlogic Украина  
Дата: 08.04.07 17:41
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

LM>Здравствуйте, minorlogic, Вы писали:


M>>Например тест.

M>>Стандарт.
M>>Здравый смысл.
M>>Деструкто то вызывается виртуальный через виртуальный вызов, и данной точке компилятор просто банально не знает размера удаляемого объекта. А знает его только в том модуле где перегружен деструктор для реального объекта.
LM>там(статическая линковка) проблема совсем не в размере объекта и освобождение памяти вызывается ПОСЛЕ отработки ВСЕХ деструкторов

Поробую на пальцах , к нам в модуль, независимо с какой линковкой пришел указатель на Base (Base*). Как компилятор этого модуля узнает скольно нужно удалить памяти , если деструктор виртуальный ? а если мы удаляем объект наследника с большим размером ?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[12]: delete this
От: LuciferMoscow Россия  
Дата: 08.04.07 17:49
Оценка:
Здравствуйте, minorlogic, Вы писали:

LM>>там(статическая линковка) проблема совсем не в размере объекта и освобождение памяти вызывается ПОСЛЕ отработки ВСЕХ деструкторов

M>Поробую на пальцах , к нам в модуль, независимо с какой линковкой пришел указатель на Base (Base*). Как компилятор этого модуля узнает скольно нужно удалить памяти , если деструктор виртуальный ? а если мы удаляем объект наследника с большим размером ?
Сколько памяти нужно освободить может знать runtime-library, например, она может писать по адресу this-X объем выделенной памяти
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[13]: delete this
От: minorlogic Украина  
Дата: 08.04.07 17:55
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

Мы можем спорить довольно долго , но нас отличает небольшой момент . Я на это тесты делал и вопрос уточнял, вы нет.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[12]: delete this
От: BoberPlus  
Дата: 08.04.07 19:03
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Здравствуйте, LuciferMoscow, Вы писали:


LM>>Здравствуйте, minorlogic, Вы писали:


M>>>Например тест.

M>>>Стандарт.
M>>>Здравый смысл.
M>>>Деструкто то вызывается виртуальный через виртуальный вызов, и данной точке компилятор просто банально не знает размера удаляемого объекта. А знает его только в том модуле где перегружен деструктор для реального объекта.
LM>>там(статическая линковка) проблема совсем не в размере объекта и освобождение памяти вызывается ПОСЛЕ отработки ВСЕХ деструкторов

M>Поробую на пальцах , к нам в модуль, независимо с какой линковкой пришел указатель на Base (Base*). Как компилятор этого модуля узнает скольно нужно удалить памяти , если деструктор виртуальный ? а если мы удаляем объект наследника с большим размером ?


ok, я тоже на пальцах

Память осбобождает не деструктор, а менеджер памяти. Ему (менеджеру) на$рать что в этой памяти хранится — объект или набор байт, например.
Re[13]: delete this
От: minorlogic Украина  
Дата: 08.04.07 19:11
Оценка:
Здравствуйте, BoberPlus, Вы писали:

BP>Память осбобождает не деструктор, а менеджер памяти. Ему (менеджеру) на$рать что в этой памяти хранится — объект или набор байт, например.


Имеет значение КАКОЙ из мнеджеров памяти удаляет объект. Я предпочитаю , чтобы тот же который и выделил эту память. Но если тебе все равно ....
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[14]: delete this
От: BoberPlus  
Дата: 08.04.07 19:32
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Здравствуйте, BoberPlus, Вы писали:


BP>>Память осбобождает не деструктор, а менеджер памяти. Ему (менеджеру) на$рать что в этой памяти хранится — объект или набор байт, например.


M>Имеет значение КАКОЙ из мнеджеров памяти удаляет объект. Я предпочитаю , чтобы тот же который и выделил эту память. Но если тебе все равно ....


Исчо раз

Менеджер памяти не может освобождать память, которую он не выделял.

Если линковка с рантаймом статическая (по умолчанию это так), то каждый dll будет иметь свой менеджер памяти, поэтому нельзя делать "delete obj", если obj был создан в другом модуле.
Re[4]: delete this
От: Аноним  
Дата: 08.04.07 19:41
Оценка: :)
_>В этом случае лучше чтоб фабрика возвращала умный указатель, который бы сам всё подчищал
А кто будет удалять сам умный указатель?
void Release(){delete this;} — нормальная практика.
Re[15]: delete this
От: minorlogic Украина  
Дата: 08.04.07 19:47
Оценка: -1
Лучше бы ты тесты сделал.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[15]: delete this
От: dotidot Россия  
Дата: 08.04.07 19:53
Оценка:
Здравствуйте, BoberPlus, Вы писали:

BP>Менеджер памяти не может освобождать память, которую он не выделял.

да какая разница, может — не может. сиравно будет плохо.
Re[15]: delete this
От: NikeByNike Россия  
Дата: 08.04.07 19:54
Оценка:
Здравствуйте, BoberPlus, Вы писали:

BP>Менеджер памяти не может освобождать память, которую он не выделял.


BP>Если линковка с рантаймом статическая (по умолчанию это так), то каждый dll будет иметь свой менеджер памяти, поэтому нельзя делать "delete obj", если obj был создан в другом модуле.


А что мешает мультитред сделать?
Нужно разобрать угил.
Re[16]: delete this
От: BoberPlus  
Дата: 08.04.07 19:58
Оценка: :)
Здравствуйте, minorlogic, Вы писали:

M>Лучше бы ты тесты сделал.

Ну что я на это кроме такого же хамства ответить могу ?
Re[16]: delete this
От: BoberPlus  
Дата: 08.04.07 20:00
Оценка:
Здравствуйте, NikeByNike, Вы писали:

NBN>Здравствуйте, BoberPlus, Вы писали:


BP>>Менеджер памяти не может освобождать память, которую он не выделял.


BP>>Если линковка с рантаймом статическая (по умолчанию это так), то каждый dll будет иметь свой менеджер памяти, поэтому нельзя делать "delete obj", если obj был создан в другом модуле.


NBN>А что мешает мультитред сделать?


чаво чаво ?
Re[16]: delete this
От: Аноним  
Дата: 08.04.07 20:31
Оценка:
M>Лучше бы ты тесты сделал.
Да ты што? Ну вот сделал тест:
Dll:
class BaseObj
{
public:
    __stdcall BaseObj(){};
    virtual __stdcall ~BaseObj()
    {
    }
    virtual void __stdcall Release()
    {
        delete this;
    }
};

extern "C" __declspec(dllexport) BaseObj *__stdcall obj_new()
{
    return new BaseObj;
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    return TRUE;
}


Exe:
#include <stdio.h>
#include <conio.h>
#include <windows.h>

class BaseObj
{
public:
    __stdcall BaseObj(){};
    virtual __stdcall ~BaseObj()
    {
    }
    virtual void __stdcall Release()
    {
        delete this;
    }
};

extern "C" __declspec(dllimport) BaseObj *__stdcall obj_new();

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    return TRUE;
}


int main(int argc, char* argv[])
{
    typedef BaseObj *(__stdcall *tobj_new)();
    tobj_new pobj_new = (tobj_new)::GetProcAddress(::LoadLibrary(TEXT("testmemdll.dll")), "_obj_new@0");

    if (!pobj_new)
    {
        printf("dll or function not found\n");
        getch();
        return -1;
    }

    printf("Press '1' to use delete or '2' to use Release\n");
    switch (getch())
    {
    case '1':
        {
            for(;;)
            {
                BaseObj *obj = pobj_new();
                delete obj;
                delete new char[256];
            }
        }
        break;
    case '2':
        {
            for(;;)
            {
                BaseObj *obj = pobj_new();
                obj->Release();
                delete new char[256];
            }
        }
        break;
    }

    return 0;
}

Скомпилял 6й студией со статическим рантаймом.. Запустил — работает 1 и 2... (нихера себе подумали суровые сибирские мужики)
Скомпилял exe шник борландовским дебилдером. Запустил 2 — работает, 1 — вылетает (агааа подумали суровые сибирские мужики)

Так вот — устойчивая работа на тестах лишь необходимое условие нормальной работы кода, тк тестами все не покроешь. Достаточное условие — соответствие документации. А документация ясно говорит:
If you choose to link with the static runtime library, then your module has its own private copy of the C/C++ runtime. When your module calls new or malloc, the memory can only be freed by your module calling delete or free. If another module calls delete or free, that will use the C/C++ runtime of that other module which is not the same as yours. Indeed, even if you choose to link with the DLL version of the C/C++ runtime library, you still have to agree which version of the C/C++ runtime to use. If your DLL uses MSVCRT20.DLL to allocate memory, then anybody who wants to free that memory must also use MSVCRT20.DLL.
(c) http://blogs.msdn.com/oldnewthing/archive/2006/09/15/755966.aspx — блог одного из главных разработчиков винды.
Re[16]: delete this
От: Аноним  
Дата: 08.04.07 20:37
Оценка:
NBN>А что мешает мультитред сделать?
Хотя бы то что стабильная работа кода в таком случае — лишь побочное следствие implementation details конкретного менеджера памяти, которая может изменится в будущем. Либо потом в будущем в вашем проекте захотят использовать другой аллокатор (например stlport с его SGI node-optimized allocator), а тут — опачки. Да и каким нить мемори трекером типа devpartner'а такой код отлаживать будет просто невозможно.
Re[17]: delete this
От: NikeByNike Россия  
Дата: 08.04.07 20:44
Оценка:
Здравствуйте, BoberPlus, Вы писали:

NBN>>А что мешает мультитред сделать?


BP>чаво чаво ?


Multi-threaded DLL
Нужно разобрать угил.
Re[17]: delete this
От: NikeByNike Россия  
Дата: 08.04.07 20:48
Оценка:
Здравствуйте, Аноним, Вы писали:

NBN>>А что мешает мультитред сделать?

А>Хотя бы то что стабильная работа кода в таком случае — лишь побочное следствие implementation details конкретного менеджера памяти, которая может изменится в будущем.
Согласен, зависит от степени универсальности... Но в принципе, мне его хватало всегда, за исключением разработки миддлеваре.

А>Либо потом в будущем в вашем проекте захотят использовать другой аллокатор (например stlport с его SGI node-optimized allocator), а тут — опачки.

А это то тут при чем??? По моему ты спутал мухи и котлеты...

А>Да и каким нить мемори трекером типа devpartner'а такой код отлаживать будет просто невозможно.

Мне всегда хватало собственных средств. Они всеравно необходимы если используешь что-нибудь типа smallallocator на подобии Александресовского.
Нужно разобрать угил.
Re[18]: delete this
От: Аноним  
Дата: 08.04.07 20:56
Оценка:
А>>Либо потом в будущем в вашем проекте захотят использовать другой аллокатор (например stlport с его SGI node-optimized allocator), а тут — опачки.
NBN>А это то тут при чем??? По моему ты спутал мухи и котлеты...
При том что при подключении STLPORT с дефолтовыми настройками new/delete вызывают не аллокатор CRT, а внутренний аллокатор STLPORT'а.
ЗЫ задолбали цитировать тупой прикол с мухами и котлетами.
Re[19]: delete this
От: NikeByNike Россия  
Дата: 08.04.07 20:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>Либо потом в будущем в вашем проекте захотят использовать другой аллокатор (например stlport с его SGI node-optimized allocator), а тут — опачки.

NBN>>А это то тут при чем??? По моему ты спутал мухи и котлеты...
А>При том что при подключении STLPORT с дефолтовыми настройками new/delete вызывают не аллокатор CRT, а внутренний аллокатор STLPORT'а.

Пускай вызывает. Это же совершенно разные вещи. Если аллокатор STLPORT'а не позволяет работать с контейнерами между dll — то это бага конкретно STLPORT, а не стандартного аллокатора.
Нужно разобрать угил.
Re[20]: delete this
От: Аноним  
Дата: 08.04.07 21:08
Оценка:
NBN>Пускай вызывает. Это же совершенно разные вещи. Если аллокатор STLPORT'а не позволяет работать с контейнерами между dll — то это бага конкретно STLPORT, а не стандартного аллокатора.
Вы не поняли. То что станартный МТ аллокатор позволяет выделять/освобождать память между длл это не его фича, а негарантируемая документацией деталь реализации. Соответственно если сторонний аллокатор эту деталь каким либо образом делает неюзабельной — никакой не баг, а просто специфика конкретное реализации, а баг — всегда в коде которые не соответствует документации. То бишь — в вашем.
Re[21]: delete this
От: NikeByNike Россия  
Дата: 08.04.07 21:32
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вы не поняли. То что станартный МТ аллокатор позволяет выделять/освобождать память между длл это не его фича, а негарантируемая документацией деталь реализации. Соответственно если сторонний аллокатор эту деталь каким либо образом делает неюзабельной — никакой не баг, а просто специфика конкретное реализации

Специфика — спецификой, но нарушение общепринятого подохода без достаточных аргументов — я бы счел багой.

А>а баг — всегда в коде которые не соответствует документации. То бишь — в вашем.

Знаешь чем отличаются баги от фич?
Нужно разобрать угил.
Re[18]: delete this
От: BoberPlus  
Дата: 09.04.07 05:34
Оценка:
Здравствуйте, NikeByNike, Вы писали:

NBN>Здравствуйте, BoberPlus, Вы писали:


NBN>>>А что мешает мультитред сделать?


BP>>чаво чаво ?


NBN>Multi-threaded DLL


Судьда, но не красиво , плюс ряд проблем связанных с динамической линковкой рантайма.
Re[22]: delete this
От: Аноним  
Дата: 09.04.07 06:29
Оценка:
А>>а баг — всегда в коде которые не соответствует документации. То бишь — в вашем.
NBN>Знаешь чем отличаются баги от фич?
Баг — поведение кода, противоречащее документации.
Re[3]: delete this
От: Sm0ke Россия ksi
Дата: 09.04.07 06:49
Оценка:
Здравствуйте, BoberPlus, Вы писали:

BP>>>Простой вопрос — допустима ли такая конструкция ?


BP>>>
BP>>>void Obj::release()
BP>>>{
BP>>>   delete this;
BP>>>}
BP>>>


BP>Объекты создаются динамически (new) фабрикой, фабрика в одной dll, созданные объекты используются в другой. "delete obj" вызывать из другой dll я по понятным причинам не могу, поэтому решил так делать.


Освобождать память надо (желательно) в том-же модуле, где она выделялась.
Если new находится в cpp файле фабрики, а методы Obj::release() разбросаны по всему проекту, то это не очень хорошо.

либо:
Перегрузите операторы new/delete в базовом классе (задефайнить в одном cpp), остальные создаваемые фабрикой классы наследуйте от него.
либо:
Поместите методы release() всех объектов в тот-же cpp, где они создаются (где фабричный метод).
Re[19]: delete this
От: Аноним  
Дата: 09.04.07 07:12
Оценка:
BP>Судьда, но не красиво , плюс ряд проблем связанных с динамической линковкой рантайма.
Одна из них — разные динамические рантаймы у разных модулей
например msvcrt.dll vs msvcr80.dll
Re[5]: delete this
От: gid_vvp  
Дата: 09.04.07 07:23
Оценка:
ПК>К сожалению, "умных" указателей нужно более одной разновидности, и дублировать их для каждого объекта не всегда удобно.
Это как?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: delete this
От: Павел Кузнецов  
Дата: 09.04.07 12:06
Оценка:
Здравствуйте, gid_vvp, Вы писали:

ПК>>К сожалению, "умных" указателей нужно более одной разновидности, и дублировать их для каждого объекта не всегда удобно.


_>Это как?


Для возвращаемого значения или других случаев, где нужно подчеркнуть передачу владения -- auto_ptr, для объекта, который никуда из данной области видимости "уплыть не должен" -- scoped_ptr, для объекта с разделяемым владением -- shared_ptr, для не владеющих ссылок на него -- weak_ptr и т.п. Если объект нельзя удалять "обычным" delete, жизнь в этом контексте становится сложнее.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
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 и прочее) стандартом С++ никак не определяется, потому любое решение основывющееся на этом — грязный хак.
Re[21]: delete this
От: Sergey Россия  
Дата: 10.04.07 13:35
Оценка:
Здравствуйте, Аноним, Вы писали:

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

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

Их нет. В стандарте ничего не говорится про dll, статическую-динамическую линковку рантайма и т.д.

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


Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[21]: delete this
От: minorlogic Украина  
Дата: 10.04.07 13:48
Оценка: -1
Здравствуйте, Аноним, Вы писали:

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

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

Тогда компилятор в топку ,я написал соверщенно коректный С++ код.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: dll_allocator?
От: Roman Odaisky Украина  
Дата: 10.04.07 15:40
Оценка:
тот, который тут: http://rsdn.ru/Forum/?mid=2018659
Автор: remark
Дата: 23.07.06
До последнего не верил в пирамиду Лебедева.
Re[21]: delete this
От: kmiken Украина  
Дата: 11.04.07 06:48
Оценка: 2 (1)
Здравствуйте, Аноним, Вы писали:


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

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

Вообще-то Ваш метод тоже основан на механизме реализации виртуальных методов. И тоже может легко не работать (правда на практике я такого не встречал). Как уже было сказано (Sergey) в стандарте нет ничего про ДЛЛ-и. и по этому любое решение будет основано на каких-то конкретных знаниях.

Предложеный Вами метод (а точнее это есть ничто иное как COM, только без подсчета ссылок и прочей виндовой белеберды), действително самый надежный способ решения __всех__ проблем. Но просто он не всегда применим, иногда появляется желание или необходимость работать не с интерфейсами а с реализацией.Хорошо это или плохо, это другой вопрос. У каждого компилятора есть свои (как правила не совместимые с другими) решения экспорта классов и говорить об универсальности решения нет никакого смысла.

ЗЫ. Вообще-то любое межмодульное взаимодействие на сегодняшний день изначально является чистым хаком с точке зрения С/С++. Ведь в общем случае никто не гарантирует, что импортируемая функция, в вашем примере obj_new(), имеет именно такую сигнатуру, или описание класса(интерфейса) с которым была собрана DLL и то что вы имеете на стороне клиента совпадают(совместимы). И все это на сегодняшний день держится на не писанных законах, правилах хорошего тона, и культуре программирования конктретных разработчиков...
Re[22]: delete this
От: BoberPlus  
Дата: 11.04.07 08:23
Оценка: 1 (1)
Здравствуйте, kmiken, Вы писали:

K>Предложеный Вами метод (а точнее это есть ничто иное как COM, только без подсчета ссылок и прочей виндовой белеберды), действително самый надежный способ решения __всех__ проблем. Но просто он не всегда применим, иногда появляется желание или необходимость работать не с

...

Вариант с Release позволяет, в том числе, уйти от delete _вообще_, то что для объекта фабрикой выделялась память, это ненужная подробность, деталь о которой знать не обязательно. Получил объект из фабрики -> поработал с ним -> освободил (Release).

На мой взгляд, очень красивое решение.
Re[23]: delete this
От: night beast СССР  
Дата: 11.04.07 09:04
Оценка:
Здравствуйте, BoberPlus, Вы писали:

K>>Предложеный Вами метод (а точнее это есть ничто иное как COM, только без подсчета ссылок и прочей виндовой белеберды), действително самый надежный способ решения __всех__ проблем. Но просто он не всегда применим, иногда появляется желание или необходимость работать не с

BP>...

BP>Вариант с Release позволяет, в том числе, уйти от delete _вообще_, то что для объекта фабрикой выделялась память, это ненужная подробность, деталь о которой знать не обязательно. Получил объект из фабрики -> поработал с ним -> освободил (Release).


BP>На мой взгляд, очень красивое решение.


казалось бы, зачем вообще нужны деструкторы когда у нас есть такой замечательный метод.
так нет же, придумывают теоретики проклятые всякие RAII и прочую ерунду.
Re[24]: delete this
От: BoberPlus  
Дата: 11.04.07 09:56
Оценка: 1 (1)
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, BoberPlus, Вы писали:


K>>>Предложеный Вами метод (а точнее это есть ничто иное как COM, только без подсчета ссылок и прочей виндовой белеберды), действително самый надежный способ решения __всех__ проблем. Но просто он не всегда применим, иногда появляется желание или необходимость работать не с

BP>>...

BP>>Вариант с Release позволяет, в том числе, уйти от delete _вообще_, то что для объекта фабрикой выделялась память, это ненужная подробность, деталь о которой знать не обязательно. Получил объект из фабрики -> поработал с ним -> освободил (Release).


BP>>На мой взгляд, очень красивое решение.


NB>казалось бы, зачем вообще нужны деструкторы когда у нас есть такой замечательный метод.

NB>так нет же, придумывают теоретики проклятые всякие RAII и прочую ерунду.

деструктор срабатывает при _удалении_ объекта и все, в случае с Release удаление может и не происходить. Объект может, например, возвращаться в пул или происходить уменьшение счетчика или что-то еще.
Re[25]: delete this
От: night beast СССР  
Дата: 11.04.07 10:05
Оценка:
Здравствуйте, BoberPlus, Вы писали:

BP>>>Вариант с Release позволяет, в том числе, уйти от delete _вообще_, то что для объекта фабрикой выделялась память, это ненужная подробность, деталь о которой знать не обязательно. Получил объект из фабрики -> поработал с ним -> освободил (Release).


BP>>>На мой взгляд, очень красивое решение.


NB>>казалось бы, зачем вообще нужны деструкторы когда у нас есть такой замечательный метод.

NB>>так нет же, придумывают теоретики проклятые всякие RAII и прочую ерунду.

BP>деструктор срабатывает при _удалении_ объекта и все, в случае с Release удаление может и не происходить. Объект может, например, возвращаться в пул или происходить уменьшение счетчика или что-то еще.


ну дык сделай обертку и в ее деструкторе делай что хочешь.
ручной контроль за счетчиком и др. подобная рутина, это не C++ way.
Re[26]: delete this
От: BoberPlus  
Дата: 11.04.07 10:17
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, BoberPlus, Вы писали:


BP>>>>Вариант с Release позволяет, в том числе, уйти от delete _вообще_, то что для объекта фабрикой выделялась память, это ненужная подробность, деталь о которой знать не обязательно. Получил объект из фабрики -> поработал с ним -> освободил (Release).


BP>>>>На мой взгляд, очень красивое решение.


NB>>>казалось бы, зачем вообще нужны деструкторы когда у нас есть такой замечательный метод.

NB>>>так нет же, придумывают теоретики проклятые всякие RAII и прочую ерунду.

BP>>деструктор срабатывает при _удалении_ объекта и все, в случае с Release удаление может и не происходить. Объект может, например, возвращаться в пул или происходить уменьшение счетчика или что-то еще.


NB>ну дык сделай обертку и в ее деструкторе делай что хочешь.

NB>ручной контроль за счетчиком и др. подобная рутина, это не C++ way.

Ну при чем здесь деструктор ?

Удаление и освобождение объекта это две разные вещи.

В случае с Release тот кто использует объект _вообще_ _не_ _знает_ будет объект удален или нет, то что с ним будет скрыто в реализации Release.

Очень даже way
Re[27]: delete this
От: night beast СССР  
Дата: 11.04.07 10:32
Оценка:
Здравствуйте, BoberPlus, Вы писали:

NB>>ну дык сделай обертку и в ее деструкторе делай что хочешь.

NB>>ручной контроль за счетчиком и др. подобная рутина, это не C++ way.

BP>Ну при чем здесь деструктор ?


при том что он вызывается автоматически (в том числе и при возникновении исключения).

BP>Удаление и освобождение объекта это две разные вещи.


BP>В случае с Release тот кто использует объект _вообще_ _не_ _знает_ будет объект удален или нет, то что с ним будет скрыто в реализации Release.


BP>Очень даже way


сам факт ручного вызова метода Release не way.
Re[28]: delete this
От: BoberPlus  
Дата: 11.04.07 10:40
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, BoberPlus, Вы писали:


NB>>>ну дык сделай обертку и в ее деструкторе делай что хочешь.

NB>>>ручной контроль за счетчиком и др. подобная рутина, это не C++ way.

BP>>Ну при чем здесь деструктор ?


NB>при том что он вызывается автоматически (в том числе и при возникновении исключения).


А delete кто будет автоматически вызывать ? Пушкин ?

BP>>Удаление и освобождение объекта это две разные вещи.


BP>>В случае с Release тот кто использует объект _вообще_ _не_ _знает_ будет объект удален или нет, то что с ним будет скрыто в реализации Release.


BP>>Очень даже way


NB>сам факт ручного вызова метода Release не way.


Release вызывается вместо delete, и внутри себя делает то что нужно, инкапсуляция однако.
Re[28]: delete this
От: BoberPlus  
Дата: 11.04.07 10:43
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, BoberPlus, Вы писали:


NB>>>ну дык сделай обертку и в ее деструкторе делай что хочешь.

NB>>>ручной контроль за счетчиком и др. подобная рутина, это не C++ way.

BP>>Ну при чем здесь деструктор ?


NB>при том что он вызывается автоматически (в том числе и при возникновении исключения).


Раз пошла такая пьянка, делаем обертку, деструктор которой вызывает release, т.е. при разрушении обертки объект будет освобожден.
Re[29]: delete this
От: night beast СССР  
Дата: 11.04.07 11:00
Оценка:
Здравствуйте, BoberPlus, Вы писали:

NB>>>>ну дык сделай обертку и в ее деструкторе делай что хочешь.

NB>>>>ручной контроль за счетчиком и др. подобная рутина, это не C++ way.

BP>>>Ну при чем здесь деструктор ?


NB>>при том что он вызывается автоматически (в том числе и при возникновении исключения).


BP>А delete кто будет автоматически вызывать ? Пушкин ?


обертка/смарт поинтер

BP>>>Удаление и освобождение объекта это две разные вещи.


BP>>>В случае с Release тот кто использует объект _вообще_ _не_ _знает_ будет объект удален или нет, то что с ним будет скрыто в реализации Release.


BP>>>Очень даже way


NB>>сам факт ручного вызова метода Release не way.


BP>Release вызывается вместо delete, и внутри себя делает то что нужно, инкапсуляция однако.


код (не стал писать кустомных делетеров):
struct test {};

shared_ptr<test> p (new test);
shared_array<test> p (new test[10]);

как с Release?
Re[29]: delete this
От: night beast СССР  
Дата: 11.04.07 11:02
Оценка:
Здравствуйте, BoberPlus, Вы писали:

NB>>>>ну дык сделай обертку и в ее деструкторе делай что хочешь.

NB>>>>ручной контроль за счетчиком и др. подобная рутина, это не C++ way.

BP>>>Ну при чем здесь деструктор ?


NB>>при том что он вызывается автоматически (в том числе и при возникновении исключения).


BP>Раз пошла такая пьянка, делаем обертку, деструктор которой вызывает release, т.е. при разрушении обертки объект будет освобожден.


да. только вот зачем тогда этот release вообще нужен?
Re[2]: delete this
От: ionicman  
Дата: 11.04.07 11:36
Оценка:
BP>>
BP>>void Obj::release()
BP>>{
BP>>   delete this;
BP>>}
BP>>

S>Допустима. Только если ты после этого использовать объект больше не будешь

А мона вопрос? Вот есть класс с такой функций, я ее вызываю —
по каоманде delete this менеджер уничтожит объект — до этого моента все ок,
НО кто сказал что он не займется кем нидь и при дальнейшем выполнении там
вместо оператора ret ( ASM ) будет какаянидь пурга?
Re[30]: delete this
От: Аноним  
Дата: 11.04.07 12:34
Оценка:
NB>
NB>struct test {};

NB>shared_ptr<test> p (new test);
NB>shared_array<test> p (new test[10]);
NB>

NB>как с Release?

struct test {};
void release_test(test *t)
{
t->Release();
}

shared_ptr<test> p (new test, release_test);
shared_array<test> p (new test[10], release_test);


Ы?

А чтоб даже ручки не чесались звать delete можно сделать так:
class test 
{
protected:
    virtual ~test(){};

public:
    test(){};
 void Release()
 {
 delete this;
 };

static void ReleaseIt(test *it)
{
it->Release();
}

};

boost::shared_ptr<test> p (new test, test::ReleaseIt);
boost::shared_array<test> a (new test[10], test::ReleaseIt);
Re[30]: delete this
От: Аноним  
Дата: 11.04.07 12:45
Оценка:
IObjectFromDll.h:

class IObjectFromDll
{
protected:
    virtual ~IObjectFromDll(){} = 0;

public:
 virtual void Release() = 0;

inline static void ReleaseIt(test *it)
{
it->Release();
}

};

Executable.cpp:

boost::shared_ptr<test> p (ObtainObjectFromDll(), test::ReleaseIt);


Логика простая — с какой такой стати код который не делал new должен звать delete? Может в той длл объект — вообще синглтон?
Re[31]: delete this
От: night beast СССР  
Дата: 11.04.07 12:46
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>А чтоб даже ручки не чесались звать delete можно сделать так:

А>class test 
А>{
А>protected:
А>    virtual ~test(){};

А>public:
А>    test(){};
А> void Release()
А> {
А> delete this;
А> };

А>static void ReleaseIt(test *it)
А>{
it->>Release();
А>}

А>};

А>boost::shared_ptr<test> p (new test, test::ReleaseIt);
А>boost::shared_array<test> a (new test[10], test::ReleaseIt);


только есть небольшая проблема. звать delete для указателя, выделенного через new[] нельзя.
когда ты пишешь свой Release, ты привязываешься к конкретному способу выделения памяти.
если еще учесть что скорее всего выделение происходит в фабрике, а освобождение разбросано по нескольким файлам с объектами, то это все не очень хорошо.
Re[31]: delete this
От: night beast СССР  
Дата: 11.04.07 12:54
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>
А>IObjectFromDll.h:
А>boost::shared_ptr<test> p (ObtainObjectFromDll(), test::ReleaseIt);
А>


А>Логика простая — с какой такой стати код который не делал new должен звать delete? Может в той длл объект — вообще синглтон?


я и не говорил что он должен звать delete
такой вопрос. в Release ты вызываешь delete. а где у тебя new происходит?
Re[32]: delete this
От: Аноним  
Дата: 11.04.07 13:14
Оценка:
Ну тоже мне проблема. Если известно что модуль test* возвращаемый ехешником — массив то реализация Release внутри выполнит корректное удаление массива. Вопрос правда — а что толку с массива объектов если мы не знаем его длину?
Re[32]: delete this
От: Аноним  
Дата: 11.04.07 13:20
Оценка:
У меня есть два модуля. Один получает указатель на интерфейс путем вызова функции другого (в котором делается new/delete или чтото еще).
Какое право имеет первый модуль звать delete на указатель который он получил не при помощи new? Откуда он знает что указатель ТАМ был создан при помощи new? (даже если положить на специфичные проблемы совместимости с рантаймами). Если объект был получен вызовом экспортной функции дллки — GetObject то вообще правильнее всего будет сделать экспортную функцию ReleaseObject для освобождения. "Но зачем две экспортируемые функции если можно сделать Release у самого объекта?" подумали MS когда делали COM и оставили только DllGetClassObject .
Re[18]: delete this
От: minorlogic Украина  
Дата: 11.04.07 13:44
Оценка: 1 (1) +1
Я дополню рассуждения.

Как в первом методе компилятор может узнать сколько памяти ему удалить ? А как вообще он узнает что память надо удалять , если оператор delete перегружен у потомка ?

Т.е. фактически первый вариант нежизнеспособен.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[18]: delete this
От: minorlogic Украина  
Дата: 11.04.07 13:45
Оценка:
Я дополню рассуждения.

Как в первом методе компилятор может узнать сколько памяти ему удалить ? А как вообще он узнает что память надо удалять , если оператор delete перегружен у потомка ?

Т.е. фактически первый вариант нежизнеспособен.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[33]: delete this
От: night beast СССР  
Дата: 11.04.07 15:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ну тоже мне проблема. Если известно что модуль test* возвращаемый ехешником — массив то реализация Release внутри выполнит корректное удаление массива. Вопрос правда — а что толку с массива объектов если мы не знаем его длину?


ну, если не проблема, покажи как переписать код на Release.
Re[33]: delete this
От: night beast СССР  
Дата: 11.04.07 15:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>У меня есть два модуля. Один получает указатель на интерфейс путем вызова функции другого (в котором делается new/delete или чтото еще).

А>Какое право имеет первый модуль звать delete на указатель который он получил не при помощи new? Откуда он знает что указатель ТАМ был создан при помощи new? (даже если положить на специфичные проблемы совместимости с рантаймами).

все вопросы справедливы и для самого объекта. откуда он знает что его создали с помошью new?
Re[34]: delete this
От: Аноним  
Дата: 14.04.07 11:11
Оценка:
NB>все вопросы справедливы и для самого объекта. откуда он знает что его создали с помошью new?
Модуль — абстрация более высокого уровня чем объект, потому объект может в принципе и знать.
Re[35]: delete this
От: night beast СССР  
Дата: 14.04.07 11:24
Оценка:
Здравствуйте, Аноним, Вы писали:

NB>>все вопросы справедливы и для самого объекта. откуда он знает что его создали с помошью new?

А>Модуль — абстрация более высокого уровня чем объект, потому объект может в принципе и знать.

раз уж вспомнил про абстракции, скажи, нужно ли объекту вообще что нибудь знать про распределение памяти?
Re[36]: delete this
От: Аноним  
Дата: 14.04.07 13:50
Оценка:
NB>раз уж вспомнил про абстракции, скажи, нужно ли объекту вообще что нибудь знать про распределение памяти?
Самому объекту — необязательно, но он может отнаследоваться от объекта который знает, и в котором реализован соответствующий Release
Re[37]: delete this
От: night beast СССР  
Дата: 14.04.07 14:01
Оценка:
Здравствуйте, Аноним, Вы писали:

NB>>раз уж вспомнил про абстракции, скажи, нужно ли объекту вообще что нибудь знать про распределение памяти?

А>Самому объекту — необязательно, но он может отнаследоваться от объекта который знает, и в котором реализован соответствующий Release

если ты хочешь поддерживать различные стратегии вделения/освобождения, то тебе придется передаать эту информацию в объект.
Re[38]: delete this
От: Аноним  
Дата: 14.04.07 14:41
Оценка: 4 (2)
NB>если ты хочешь поддерживать различные стратегии вделения/освобождения, то тебе придется передаать эту информацию в объект.
Дану?

//Interface.h:
class IExportedObject
{
public:
    virtual void Release() = 0;
};

class IBusinessLogicObject : public IExportedObject
{
public:
    virtual void Foo() = 0;
};


//BusinessLogic.*:
class MyObject : public IBusinessLogicObject 
{
public:
    virtual ~MyObject()
    {
        printf("~MyObject\n");
    }
    virtual void Foo()
    {
        printf("Foo\n");
    }
};

//ExportIntafaces.*:
template <class T>
class ExportSingle : public T
{
public:
    virtual ~ExportSingle()
    {
        printf("~ExportSingle\n");
    }

    virtual void Release()
    {
        delete this;
    }
};

template <class T>
class ExportArray : public T
{
public:
    virtual ~ExportArray()
    {
        printf("~ExportSingle\n");
    }
    virtual void Release()
    {
        delete[] this;
    }
};


extern __declspec(dllexport) IBusinessLogicObject *CreateObject()
{
    return new ExportSingle<MyObject>;
}

extern __declspec(dllexport) IBusinessLogicObject *CreateObjects(int n)
{
    return new ExportArray<MyObject>[n];
}


//application
int main(int argc, char * argv[])
{
    IBusinessLogicObject *object = CreateObject();
    object->Release();
    
    IBusinessLogicObject *objects = CreateObjects(10);
    objects->Release();
    
    return 0;
}
Re[39]: delete this
От: night beast СССР  
Дата: 14.04.07 16:56
Оценка:
Здравствуйте, Аноним, Вы писали:

NB>>если ты хочешь поддерживать различные стратегии вделения/освобождения, то тебе придется передаать эту информацию в объект.

А>Дану?

+1

о таком не подумал.
однако по прежнему не совсем видны преимущества по сравнению с враппером с кустомным делетером.
Re[40]: delete this
От: Аноним  
Дата: 15.04.07 12:31
Оценка:
NB>о таком не подумал.
NB>однако по прежнему не совсем видны преимущества по сравнению с враппером с кустомным делетером.
А это и есть враппер с кастомным делетером. Только более языко-платформно-независимый чем возврат boost::shared_ptr'а.
Re[41]: delete this
От: Аноним  
Дата: 15.04.07 12:36
Оценка: 1 (1) +1
А>А это и есть враппер с кастомным делетером. Только более языко-платформно-независимый чем возврат boost::shared_ptr'а.
Поясню. Что должен сделать программист на делфи или .Net чтобы использовать длл, возвращающую boost::shared_ptr?
Re[42]: delete this
От: night beast СССР  
Дата: 15.04.07 14:24
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>>А это и есть враппер с кастомным делетером. Только более языко-платформно-независимый чем возврат boost::shared_ptr'а.

А>Поясню. Что должен сделать программист на делфи или .Net чтобы использовать длл, возвращающую boost::shared_ptr?

опыта работы с .нет нету, поэтому ничего не скажу.
Re[18]: delete this
От: Erop Россия  
Дата: 04.09.07 08:36
Оценка:
M>
M>static void* operator new (size_t s)
M>{
M>    printf("new from native module\n");
M>    return malloc(s);
M>}

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


Это противоречит стандарту! operator new/delete должны быть либо методами классов/стркутур, либо функциями в глобальном пространстве имён с внешней линковкой!!!

M>Еще раз повторяю , что используется для удаления менежер памяти , именно то который и создавал. А после эксперимента , уберите виртуальный деструктор.

Ну всё хорошо, только надо у example ещё operator new/delete перекрыть!!!

Например, так:
struct CSafeDeletableBase {
    virtual ~CSafeDeletable() {}
    
    void* operator new( size_t size ) { return ::operator new( size ); }
    void operator delete( void* block ) { ::operator delete( block ); }

    // Дальнейшие шаблоны по желниаю....
    template<typename T1>
        void* operator new( size_t size, T1 a1 ) 
            { return ::operator new( size, a1 ); }
    template<typename T1>
        void operator delete( void* block, T1 a1 ) 
            { return ::operator delete( block, a1 ); }
         
    template<typename T1, typename T2>
        void* operator new( size_t size, T1 a1, T2 a2 ) 
            { return ::operator new( size, a1, a2 ); }
    template<typename T1, typename T2>
        void operator delete( void* block, T1 a1, T2 a2 ) 
            { return ::operator delete( block, a1, a2 ); }
         
    // и т. д.
};

Ну и потом выводить из CSafeDeletableBase всё, что может удаляться из разных модулей...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: delete this
От: Erop Россия  
Дата: 04.09.07 08:41
Оценка:
Здравствуйте, gid_vvp, Вы писали:

BP>>Объекты создаются динамически (new) фабрикой, фабрика в одной dll, созданные объекты используются в другой. "delete obj" вызывать из другой dll я по понятным причинам не могу, поэтому решил так делать.


_>В этом случае лучше чтоб фабрика возвращала умный указатель, который бы сам всё подчищал


При таком подходе можно нечаянно всё только запутать
Умный указатель обычно шаблон, соответсвенно где именно реализуются и куда линкуются методы шаблона вопрос философский (оч. зависит от того, что где кому и как. Палтформы там, компилятора, опций...) Соответсвенно из какой dll возмётся operator delete никто не знает ((
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[20]: delete this
От: Erop Россия  
Дата: 04.09.07 09:02
Оценка:
Здравствуйте, minorlogic, Вы писали:

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


Твоё решение несовместимо, увы.

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

Нет. Это всё по стандарту.

Смотри.
Вызоав правильного мэнеджера гарантирует нифига не виртуальный деструктор, а operator new/delete определённые у класса.
А виртуальный деструктор призван решать другую проблему -- вызывать нужный деструктор из иерархии. При этом может возникнуть неприятная ситуация, когда у разных членов иерархии используются разные мэнеджеры памяти. Стандарт эту тему нынче разрудивает (это случилось вовсе и не сразу, кстати, но таких старых компилятором найти трудно). Так что если у класса есть виртуальный деструктор и есть перекрытый operator delete, то компилятор обязан позвать нужный operator delete. Так как ни DLL ни разных глобальных operator delete в стандарте нет, то и никакой спецификации на этот случай нет. И авторы компиляторов могут делать так, как им нравится. Например, им может нравится inline opearator delete, что обречёт их избегать, по возможности, виртуальности при его вызове...

Но, тем не мнее, в твоей идее, ИМХО, есть здравое зерно. Типа раз уж мы вводим виртуальный деструктор, то стоит и operator new/delete перекрыть. Типа ПРИГОДДИТСЯ (с) изв. анекдот
Ну а чтобы не так муторно было перекрывать, надо написать один раз базу
Автор: Erop
Дата: 04.09.07
, где всё перекрыто и объявлено, а потом из неё выводиться
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: delete this
От: Erop Россия  
Дата: 04.09.07 09:06
Оценка:
Здравствуйте, Sergey, Вы писали:

А>>Если такое решение требует отдельного изучения реализации таблицы виртуальных методов в каждом из компиляторов — извольте. Мне нужен С++ решение.


S>Их нет. В стандарте ничего не говорится про dll, статическую-динамическую линковку рантайма и т.д.


зато говорится всё-таки о менеджерах памяти в виде операторов new и delete.
смотри тут
Автор: Erop
Дата: 04.09.07
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[15]: delete this
От: Erop Россия  
Дата: 04.09.07 09:15
Оценка:
Здравствуйте, BoberPlus, Вы писали:

BP>Если линковка с рантаймом статическая (по умолчанию это так), то каждый dll будет иметь свой менеджер памяти, поэтому нельзя делать "delete obj", если obj был создан в другом модуле.


Только если ты не перекрыл и экспортировал operator new/delete для своего кроссDLLьного объекта
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.