Как "вынудить" программиста юзать "смарт-указатель"? (C++)

Модератор: Модераторы разделов

Аватара пользователя
Zeus
Сообщения: 694

Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

Задача:
Есть класс, указатель на объект которого возвращает некоторая функция.
Нужно обеспечить удаление этого объекта после того как он станет не нужен.
Когда он станет не нужен - знает только программист, вызвавший функцию, но он может забыть удалить его.
Решением было бы - передавать указатель на этот объект некоему подобию smart-pointer'а, который разрушаясь удалял бы объект.
Псевдокод:

Код: Выделить всё

...
{
Obj* obj=repository.getObject("objectName");
Obj_var ov (obj)
ov->getName(); // Получить имя объекта
ov->setAttr("time", 10l); // Установить значение аттрибута
...
//.. тут что-то ещё делается
...
// и вот тут, объект ov разрушается и удаляет объект obj
}

Но вообще-то вся функциональность содержится в объекте obj и программист может вызывать те же методы и у него.
А как можно вынудить программиста работать только через вспомогательный объект Obj_var?

Единственное что приходит в голову: закрыть все методы у Obj а Obj_var объявить friend'ом.
Но как-то... не нравятся мне все эти friend'ы - я это ключевое слово никогда раньше даже и не использовал.

Есть какие-нибудь ещё варианты?
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

Только что вот сам придумал: к закрытым членам имеет доступ другой объект этого же класса.
Можно наделить функциями смарт-указателя сам же класс и "скармливать" ему указатель на объект этого же типа....

Код: Выделить всё

{
Obj* obj=repository.getObject("objectName");
Obj ov (obj)
ov->getName(); // Получить имя объекта
ov->setAttr("time", 10l); // Установить значение аттрибута
...
//.. тут что-то ещё делается
...
// и вот тут, объект ov разрушается и удаляет объект obj
}

Во бред-то! :crazy:

Программёр, наверное, с ума сойдёт:
получил указатель, но вызывать функции не моги! (исключения, например, будут вываливаться)
Нужно создать ещё один объект этого же типа и вызывать функции у него! :D
Спасибо сказали:
Аватара пользователя
Liksys
Сообщения: 2910

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Liksys »

Zeus, за последний месяц заметил уже несколько твоих тем, причем в каждой изобретался какой-то хитрый хак :) Что ж ты пишешь такое? :)
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergio »

Zeus писал(а):
15.11.2007 00:59
Задача:
Есть класс, указатель на объект которого возвращает некоторая функция.
Нужно обеспечить удаление этого объекта после того как он станет не нужен.
Когда он станет не нужен - знает только программист, вызвавший функцию, но он может забыть удалить его.

Мну кажецо, автор вопроса ставит оффтопичную задачу - более из области социальной инженерии, чем программирования. :crazy:
"Как заставить программиста не забыть удалить объект..." Гыг. Например, можно написать БАЛШИМИ КРАСНЫМИ БУКВОМИ: "КТО ЗАБУДЕТ УДАЛИТЬ УКАЗАТЕЛЬ В КОНЦЕ РАБОЧЕГО ДНЯ ТОТ САМ СИБЕ ЗЛОБНЫЙ БУРАТИНА И ЗА ПРЕМИЕЙ ПУСТЬ ИДЕТ К ПАПО КАРЛО". :happy:
Если программист боится, что он забудет удалить объект - он сам полученный указатель завернет в смарт. =)
Альтернатив вижу две:
1) Завернуть в смарт и его выдать программисту. Минус - навязываете свои смарты (стандартных пока нет, как будто? auto_ptr не в счет), с которым данный программист может не уметь работать или его не любить.
2) Возвращать не указатель, а объект. Если ваш "объект" плох для копирования или не должен копироваться - значит создаем легковесную обертку, реализующую весь нужный интерфейс, хранящую указатель на собственно объект, а собственно объект содержит также счетчик ссылок...
Как видите, чем глаже тем гаже, чем дальше в лес тем толще партизаны. Проще всего отдавать raw поинтер, и пускай программер сам пишет

Код: Выделить всё

scoped_ptr<SomeObject> p_obj(repository.getObject("objectName"));

если ему надо, или сам следит за raw поинтерами и сам себе будет злобным буратиной если невнимателен.

Решением было бы - передавать указатель на этот объект некоему подобию smart-pointer'а, который разрушаясь удалял бы объект.

Так никто и не мешает. Но если так - то это не ваша уже забота. ))
Но вообще-то вся функциональность содержится в объекте obj и программист может вызывать те же методы и у него.
А как можно вынудить программиста работать только через вспомогательный объект Obj_var?
Единственное что приходит в голову: закрыть все методы у Obj а Obj_var объявить friend'ом.
Но как-то... не нравятся мне все эти friend'ы - я это ключевое слово никогда раньше даже и не использовал.
Есть какие-нибудь ещё варианты?

Смотря для чего конкретно.
Можно не давать программисту объект, а давать смартптр. Или прокси-объект к шаред объекту.
Чтобы программист не мог работать с объектом напрямую ему можно не давать определение класса объекта. ))


Liksys писал(а):
15.11.2007 01:22
Zeus, за последний месяц заметил уже несколько твоих тем, причем в каждой изобретался какой-то хитрый хак :) Что ж ты пишешь такое? :)

Я знаю. Бедный Zeus пытается обхитрить всех домохозяек и для этого изобретает мегадуроупорную защиту от дурака ("прикладного программиста" ака "ламера", гыгы) на все случаи жизни. ))) Zeus, это же аксиома: не бывает абсолютной защиты от дураков. :crazy:
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

Liksys писал(а):
15.11.2007 01:22
Zeus, за последний месяц заметил уже несколько твоих тем, причем в каждой изобретался какой-то хитрый хак :) Что ж ты пишешь такое? :)

Извращённый моск у меня, наверное :D

Да всякое пишу: и по работе и, блин, всё движок для АСУ ТП под Linux (точнее - максимально кросс-платформенный) выдумываю!

В данном конкретном случае ситуация такая:
есть "суп" из объектов разных классов, отнаследованных от базового класса Object (тут я извратиться не смог - название стандартное :dry: ).
Программист очередного класса захочет воспользоваться функциональностью некоторого объекта.
Он каким-то образом находит его по имени - получает указатель на него.
Сохраняет и пользуется довольный.

А через какое-то время объект удалили. Указатель на него стал недействительным, а программёр об этом и не знает, пока на корке не упадёт.

Я решил, что программисту будет возвращаться указатель не на сам объект Object, а некоторый "прокси": Object_proxy (в примерах он Obj назван).
Этот "прокси" будет создаваться в интересах конкретного объекта, будет иметь с ним двустороннюю связь и всё взаимодействие с объектом будет осуществляться через прокси. Т.е. программисту никак будет не получить указатель на сам объект - только прокси.
Время жизни прокси - не такое как у объекта: он "живёт" пока нужен программисту, которому его выдали.
Но в то же время он (прокси) "знает", когда объект, к которому он "привязан" удаляют: после этого он на все вызовы программиста будет отвечать исключением ObjectNotExists.

Ладно, получил программист указатель на прокси - а он ему нужен-то только чтобы пару-тройку функций вызвать и всё - можно удалять.
И хорошо если он не забыл его удалить, а если забыл?
Вот чтобы самый "забывчивый" программист удалил за собой ненужные объекты, я и задумал что-то вроде смарт-указателя уже для прокси.
А чтобы вынудить программиста использовать этот смарт-указатель, нужно сделать так, чтобы он не мог дёргать методы прокси напрямую.

Получается такая "структурная" цепочка: Object <-> Object_proxy <-> Proxy_var
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

sergio писал(а):
15.11.2007 01:40
Если программист боится, что он забудет удалить объект - он сам полученный указатель завернет в смарт. =)

Это не наш подход. В ж/д автоматике такой неприемлем!

sergio писал(а):
15.11.2007 01:40
1) Завернуть в смарт и его выдать программисту.

А когда и кто будет удалять смарт?

sergio писал(а):
15.11.2007 01:40
Минус - навязываете свои смарты (стандартных пока нет, как будто? auto_ptr не в счет), с которым данный программист может не уметь работать или его не любить.

Программист пишет компонент для системы и должен следовать её ограничениям.

sergio писал(а):
15.11.2007 01:40
2) Возвращать не указатель, а объект. Если ваш "объект" плох для копирования или не должен копироваться - значит создаем легковесную обертку, реализующую весь нужный интерфейс, хранящую указатель на собственно объект, а собственно объект содержит также счетчик ссылок...

Исходим из того, что объект "плох" для копирования.
Собственно, для многих объектов операция копирования вообще не имеет смысла: например это - программный двойник реального датчика.
А когда и кто будет удалять "легковесную обёртку"?

sergio писал(а):
15.11.2007 01:40
Как видите, чем глаже тем гаже, чем дальше в лес тем толще партизаны. Проще всего отдавать raw поинтер, и пускай программер сам пишет

Код: Выделить всё

scoped_ptr<SomeObject> p_obj(repository.getObject("objectName"));

если ему надо, или сам следит за raw поинтерами и сам себе будет злобным буратиной если невнимателен.

Это не наш подход! У нас должен быть "трёхкратный запас надёжности".

sergio писал(а):
15.11.2007 01:40
Решением было бы - передавать указатель на этот объект некоему подобию smart-pointer'а, который разрушаясь удалял бы объект.

Так никто и не мешает. Но если так - то это не ваша уже забота. ))

"Нет наша!" (с) Берегись автомобиля :D

sergio писал(а):
15.11.2007 01:40
Можно не давать программисту объект, а давать смартптр. Или прокси-объект к шаред объекту.

А кто будет удалять "смартптр"?

sergio писал(а):
15.11.2007 01:40
Чтобы программист не мог работать с объектом напрямую ему можно не давать определение класса объекта. ))

А как он получит указатель на него?
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergio »

Zeus писал(а):
15.11.2007 01:57
Это не наш подход! У нас должен быть "трёхкратный запас надёжности".

С этого бы и начали. ))

Zeus писал(а):
15.11.2007 01:57
sergio писал(а):
15.11.2007 01:40
1) Завернуть в смарт и его выдать программисту.

А когда и кто будет удалять смарт?

Эээ?? В смысле?? Смарты никто не удаляет. А то нафига было их создавать? ))))))))
Если шаред - то возвращаете бай вэлью и всё. Когда последний экземпляр у ламера выходит из поля зрения - он со стэка удляется, декреметит счетчик ссылок в боди, и если там ноль то боди себя делетит. Или я не понял вопроса?

Zeus писал(а):
15.11.2007 01:57
sergio писал(а):
15.11.2007 01:40
2) Возвращать не указатель, а объект. Если ваш "объект" плох для копирования или не должен копироваться - значит создаем легковесную обертку, реализующую весь нужный интерфейс, хранящую указатель на собственно объект, а собственно объект содержит также счетчик ссылок...

Исходим из того, что объект "плох" для копирования.
Собственно, для многих объектов операция копирования вообще не имеет смысла: например это - программный двойник реального датчика.
А когда и кто будет удалять "легковесную обёртку"?

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

Zeus писал(а):
15.11.2007 01:57
sergio писал(а):
15.11.2007 01:40
Можно не давать программисту объект, а давать смартптр. Или прокси-объект к шаред объекту.

А кто будет удалять "смартптр"?


Выше было. ))))

Zeus писал(а):
15.11.2007 01:57
sergio писал(а):
15.11.2007 01:40
Чтобы программист не мог работать с объектом напрямую ему можно не давать определение класса объекта. ))

А как он получит указатель на него?

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

(занудным голосом) А вообще, если вам троекратный запас - то вам надо отдельные процессы, клиент-серверную систему... )))
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergeyvp »

Zeus писал(а):
15.11.2007 01:45
Он каким-то образом находит его по имени - получает указатель на него.
Сохраняет и пользуется довольный.

А через какое-то время объект удалили. Указатель на него стал недействительным, а программёр об этом и не знает, пока на корке не упадёт.

Я может не понял фишки, но в GObject например, пока не удалится последний указатель на объект его содержимое остаётся доступным по существующим указателям. То есть объект перестаёт существовать только после удаления всех указателей на него. Вы на чём пишите?
Спасибо сказали:
Аватара пользователя
Liksys
Сообщения: 2910

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Liksys »

Zeus, написал бы уж garbage collection чтоли... Сразу бы весь этот изврат ушел :) Насколько я знаю, T++ например, эт который для распределенных вычислений, надстройка над C++, так и сделан.

sergeyvp, на плюсах, ясен пень)
Спасибо сказали:
Serik
Сообщения: 149
ОС: SuSE Linux

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Serik »

Всяческие умные, умнейшие и гениальные указатели, скрытие методов и пр. хорошо освещается в Элджер Д. C++: библиотека программиста
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

sergio
Хм.... "by value", в этом что-то есть.

sergeyvp
GObject - это что? Из какой области человеческого знания?

all
Спасибо, Чапай будет думать :)
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergio »

Zeus писал(а):
15.11.2007 11:29
sergeyvp
GObject - это что? Из какой области человеческого знания?

Из Gнутой области. )))
glib библиотечка базового б-менее универсального функционала, используется под ГТК2 и др.
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergeyvp »

Zeus писал(а):
15.11.2007 11:29
sergeyvp
GObject - это что? Из какой области человеческого знания?

Вот из этой http://linfoline.homedns.org/API/gobject/index.html , вы же вроде GTK+ используете, вот это всё оттуда.
Вобще я не сразу понял что тут про плюсы, извиняюсь, залез не в свою тему :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

Понятно.

Не, это не GTK'шный проект. Чистый C++.
И задача стоит не
"не удалять объект, пока у кого-то на него есть указатели",
а
"удалить, но при попытке юзеров воспользоваться имеющимися у них "указателями" - выдавать ошибку вместо корки"
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergeyvp »

Zeus писал(а):
15.11.2007 15:21
"удалить, но при попытке юзеров воспользоваться имеющимися у них "указателями" - выдавать ошибку вместо корки"

Я собственно и удивился что такое вобще возможно (наличие указателей на несуществующий объект) поэтому и переспросил :) (про С++ ничего не знаю)
В чистом Си с применением GObject такой ситуации в принципе не может возникнуть, на сколько я знаю.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение drBatty »

Zeus писал(а):
15.11.2007 15:21
Понятно.

Не, это не GTK'шный проект. Чистый C++.
И задача стоит не
"не удалять объект, пока у кого-то на него есть указатели",
а
"удалить, но при попытке юзеров воспользоваться имеющимися у них "указателями" - выдавать ошибку вместо корки"

Писал я вчера что-то подобное, не вижу ничего особо сложного здесь. Создай класс, и дай его своим юзерам(вместе с описанием, конечно). понадобится юзеру создать объёкт - пажалуйста, конструктор имеется. Надо удалить - есть и деструктор. В чём проблема? Если юзер удалил объект - он всё равно может воспользоватся:

Код: Выделить всё

class obj
{
public:
 obg();
 void metod()
 {
   if(!data)
    {}//error
 }
 ~obj()
 {
  if(!data)
    {}//ошибка!
  delete data;
  data = NULL;
 }
}

int main()
{
 obj x;//создание
 x.~obj()//удаление
 x.metod()//вызов метода приводит к ошибке
}

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

sergeyvp писал(а):
15.11.2007 16:51
Я собственно и удивился что такое вобще возможно (наличие указателей на несуществующий объект)

В любом си возможен указатель на несуществующий объект. В смысле указатель на неописаный объект возможен:

Код: Выделить всё

class ttt;

ttt *ptr;

class ttt
{
...
};

Вроде и в си тоже можно написать:

Код: Выделить всё

struct ttt
{
 ttt *ptr;
};
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergio »

drBatty писал(а):
16.11.2007 22:18

Код: Выделить всё

class obj { }

int main() {
 obj x;//создание
 x.~obj()//удаление
 x.metod()//вызов метода приводит к ошибке
}

Вызов дтора - это все же не удаление, а разрушение, деинициализация. ))
После действительно удаления, если метод виртуальный, то на практике его вызов приводит к андефайнд бихэвио... с возможность сегфолта. И подозреваю, что в теории (стандарте то бишь) любой вызов метода не сконструированного объекта (т.е. напр. после вызова дтора) есть все тот же андефайнд бихэвио...

Вроде и в си тоже можно написать:

Код: Выделить всё

struct ttt
{
 ttt *ptr;
};


если в си - то

Код: Выделить всё

struct ttt *ptr;
)))

Кстати, не понял, что в вашем примере есть data и откуда оно береццо...
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

drBatty, честно говоря мало что понял.
Ошарашен только несколько... нестандартным подходом к "удалению" объекта.

Задача состоит в том, чтобы программа не падала, когда программист воспользуется указателем на уже несуществующий объект.
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение v04bvs »

Zeus писал(а):
15.11.2007 00:59
А как можно вынудить программиста работать только через вспомогательный объект Obj_var?


1. Пусть функция возвращает умный указатель, а не обычный.
2. Пригрозить программисту лишением премии.

Zeus писал(а):
16.11.2007 23:20
Задача состоит в том, чтобы программа не падала, когда программист воспользуется указателем на уже несуществующий объект.

Никак. Если Windows, то можно как то ловить Access violations, но это не надёжно, не правильно, и вообще.

И вообще, С++ - идеальный язык для отстрела ног. Мешать этому - только подкладывать ещё более хитроумные грабли, которые ногу всё равно отстрелят, вот только так хитро, что и сам не поймёшь, что это было. Просто надо понимать, что грабли раскиданы везде, и пусть лучше они лежат "явно" - тогда их будет видно. Дурак на них наступит, на то он и дурак, а умный их обойдёт.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение drBatty »

sergio писал(а):
16.11.2007 22:55
drBatty писал(а):
16.11.2007 22:18

Код: Выделить всё

class obj { }

int main() {
 obj x;//создание
 x.~obj()//удаление
 x.metod()//вызов метода приводит к ошибке
}

Вызов дтора - это все же не удаление, а разрушение, деинициализация. ))
После действительно удаления, если метод виртуальный, то на практике его вызов приводит к андефайнд бихэвио... с возможность сегфолта. И подозреваю, что в теории (стандарте то бишь) любой вызов метода не сконструированного объекта (т.е. напр. после вызова дтора) есть все тот же андефайнд бихэвио...

Вот в том то и дело! Объект у нас сконструирован, а затем для него вызван деструктор. Если мы приняли меры предосторожности - мы можем вызвать метод. Необходимо понять, что в С++ деструктор, это всего-лишь метод, просто он часто вызывается неявно. Никакой деструктор не удаляет объект, в нём просто прописаныы действия, которые требуются выполнить перед удалением. Топикстартеру необходим костыль, для выполнения каких-то действий после удаления, что с того, что я вызвал деструктор явно?
Кстати, не понял, что в вашем примере есть data и откуда оно береццо...

data это указатель, выделяемый new(возможно эта new перезагружена). Может принимать значение NULL, что означает - "неинициализировано"

2Zeus А что вас так "ошарашило"? Вот чуть выше Serik кинул полезную ссылку на книгу, там ещё веселее есть строчки, к примеру

Код: Выделить всё

delete *this;

Книга, кстати, очень нужная и полезная.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение drBatty »

v04bvs писал(а):
17.11.2007 00:41
Zeus писал(а):
16.11.2007 23:20
Задача состоит в том, чтобы программа не падала, когда программист воспользуется указателем на уже несуществующий объект.

Никак.

Да ладно! Если это смарт указатель, он сможет создать новый объект, да и вообще - сделать всё что угодно. Вот только как этот объект удаляли? Если вынули диск из компа и разрезали его болгаркой - это да... А вот если сделали delete, совсем другое: вопервых вызовется наш деструктор, а во вторых никто не помешает нам перезагрузить delete ;)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

v04bvs писал(а):
17.11.2007 00:41
Zeus писал(а):
15.11.2007 00:59
А как можно вынудить программиста работать только через вспомогательный объект Obj_var?

1. Пусть функция возвращает умный указатель, а не обычный.

Вот мы к этому и пришли. Только не "умный указатель", а "прокси".

v04bvs писал(а):
17.11.2007 00:41
2. Пригрозить программисту лишением премии.

Я по образованию - СЦБист (это - железнодорожная автоматика).
СЦБисты все помешаны на безопасности.
И если бы она достигалась только организационными методами (лишением премии), то у нас бы каждую неделю поезда под откос летали.
В ж/д автоматике безопасность достигается специальными техническими средствами и приёмами.
Человеческий фактор, ясное дело, до конца не устранишь, но как только появляется техническое решение, которое может его снизить и которое может пройти сертификацию на безопасность - оно применяется.
Вот и в программировании: чем грозить программисту пальчиком - я лучше не дам ему сделать что-то некорректное.

v04bvs писал(а):
17.11.2007 00:41
Zeus писал(а):
16.11.2007 23:20
Задача состоит в том, чтобы программа не падала, когда программист воспользуется указателем на уже несуществующий объект.

Никак. Если Windows, то можно как то ловить Access violations, но это не надёжно, не правильно, и вообще.

Именно, что "как". Это-то довольно просто - с теме об этом уже написано.

drBatty писал(а):
17.11.2007 11:15
2Zeus А что вас так "ошарашило"? Вот чуть выше Serik кинул полезную ссылку на книгу, там ещё веселее есть строчки, к примеру

Код: Выделить всё

delete *this;

Книга, кстати, очень нужная и полезная.

Книгу я уже читаю.
Ошарашил непосредственный вызов деструктора.
Может когда я дочитаю книгу до конца - пойму это, но сейчас, встретился бы мне где-то в коде вызов деструктора, я был бы сильно удивлён.

До

Код: Выделить всё

delete *this
- тоже не допёр: зачем указатель разыменовывать?
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergio »

drBatty писал(а):
17.11.2007 11:15
Вот в том то и дело! Объект у нас сконструирован, а затем для него вызван деструктор. Если мы приняли меры предосторожности - мы можем вызвать метод. Необходимо понять, что в С++ деструктор, это всего-лишь метод, просто он часто вызывается неявно. Никакой деструктор не удаляет объект, в нём просто прописаныы действия, которые требуются выполнить перед удалением. Топикстартеру необходим костыль, для выполнения каких-то действий после удаления, что с того, что я вызвал деструктор явно?

Ну, маленькое формальное уточнение: это не просто метод, а метод для которого жестко задан прототип, и который не должен кидать исключения. ))) Логическое уточнение. Объект либо сконструирован, либо нет. Если объект не сконструирован - им пользоваться не должно. Вы предлагаете ввести в и без того не самый прозрачный язык еще и объекты с магическим состоянием "недобитый объект". Пользоваться нельзя, но когда пинаешь его - он мычит. )))) Цэ называецо хак.
Я и про более извращенный хак знаю - когда внутри метода объекта вызывается его деструктор, а затем placement new. Это тоже хак. "Почти завсегда работающий" и совершенно некорректный идеологически. Но его хотя бы "почти не видно" снаружи. А ваш - вводит новую логику использования объектов и языка в целом.
Мну не одобряет. :happy:
2Zeus А что вас так "ошарашило"? Вот чуть выше Serik кинул полезную ссылку на книгу, там ещё веселее есть строчки, к примеру

Код: Выделить всё

delete *this;

Книга, кстати, очень нужная и полезная.

Если там именно такие "веселые строчки" - то я бы хотел почитать, что же они делают. :happy:
Если же все-таки

Код: Выделить всё

delete this;

- то это совершенно корректная и узаконенная операция. Замечательно применяется например в том самом шаред боди, при отвязывании ссылающихся указателей-прокси:

Код: Выделить всё

void SharedBody::release(void)  {
  if (0 == -- _refcount)  delete this;
  return;
}
Незаконны лишь явные или неявные обращения к объекту после делит. А выполнить, к примеру, ретурн и выйти из метода объекта вам никто не мешает.
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение drBatty »

sergio писал(а):
17.11.2007 14:30
Ну, маленькое формальное уточнение: это не просто метод, а метод для которого жестко задан прототип, и который не должен кидать исключения. ))) Логическое уточнение. Объект либо сконструирован, либо нет. Если объект не сконструирован - им пользоваться не должно. Вы предлагаете ввести в и без того не самый прозрачный язык еще и объекты с магическим состоянием "недобитый объект". Пользоваться нельзя, но когда пинаешь его - он мычит. )))) Цэ называецо хак.

угу. Програмисту сказали: "не юзай после удаления", а он заюзал. В этой ситуации без недобитого объекта не обойтись, к примеру ввести прокси, который и будет "недобитым обектом"(после удаления). Т.е. пинаем прокси, а он мычит. Если вам так удобнее - пожалуйста. Мне удобнее было сам объект наделить аж тремя состояниями:
1) объект содержит данные
2) обект содержит общие данные вместе с несколькоми другими объектами(это не ссылка, что-то вроде mount --bind)
3) обект содержит ссылку на константные данные, которые не может изменить не сам объект, ни тот код с которым обект работает.
Я написал довольно сложный деструктор и несколько конструкторов. Теперь могу забыть про удаление и создание обектов, мне всё равно когда они создаются и убиваются, например если какойто метод хочет изменить данные(вида2 и 3) - автоматом создаётся копия данных. В третьем состоянии я сознательно оставил дыру - данные не сможет изменить ни обект, ни его пользователи, однако их может менять сам создатель(в т.ч. удалять), это можно с лёгкостью исправить. Самое паганое в си++ это то, что конструктор не может вернуть код ошибки. Поэтому либо надо пользоватся костылём исключений, либо ввести недаделаные обекты и метод для их доделки, а в самом конструкторе ошибок быть не может. Если вы не согласны - идите в мир Windows и юзайте MFC с CFile, там как раз файлы в конструкторе открываются...
Я и про более извращенный хак знаю - когда внутри метода объекта вызывается его деструктор, а затем placement new. Это тоже хак. "Почти завсегда работающий" и совершенно некорректный идеологически. Но его хотя бы "почти не видно" снаружи. А ваш - вводит новую логику использования объектов и языка в целом.
Мну не одобряет. :happy:

мну - тоже. А как без хаков устранять послетствия хаков? Кстати, почему "почти"? У меня всегда работает... Шучу, я так не делаю, обычно можно и по другому сделать.
Если же все-таки

Код: Выделить всё

delete this;

- то это совершенно корректная и узаконенная операция.

конечно без звёздочки! ОписАлся :)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение drBatty »

Zeus писал(а):
17.11.2007 12:27
Именно, что "как". Это-то довольно просто - с теме об этом уже написано.

это просто пока у тебя 3 глобальных переменных типа int, и всё. А обратная раскрутка стека и вызов всех деструкторов после исключения - очень сложная вещь, особенно если есть недобитые объекты.
Книгу я уже читаю.
Ошарашил непосредственный вызов деструктора.
Может когда я дочитаю книгу до конца - пойму это, но сейчас, встретился бы мне где-то в коде вызов деструктора, я был бы сильно удивлён.

такая строчка появится если необходим недобитый объект, в нашем случае он необходим, если объект удалить обычным delete, то его нелзья не только использовать, но даже узнать, что он удалён(без грязных хаков). Значит нужна либо необычная delete(язык и не такое позволяет), либо как-нибудь по другому удалять объекты. Для надёжности можно ввести в деструктор проверку, как именно удаляется объект(это обычно можно сделать без хаков). Можно вообще ничего не удалять, написать сборку мусора(а можно и не писать, просто проверять сколько памяти жрёт приложение, и если известна граница - просто вывалится с кодом ошибки)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение drBatty »

Кстати, как я решил бы эту задачу: я перезагрузил delete таким образом, что кроме удаления, указателю присваивалось значение особого статического экземпляра класса. Этот экземпляр всеми методами будет выдавать ошибку. И не надо никаких прокси, это может привести к ошибкам, а ошибки недопустимы по условию.

PS: упс... Написал фигню. Програмисту вообще нельза давать ни new ни delete. Для этого достаточно закрыть дефолтный конструктор и конструктор копирования. Тогда программер не сможет создавать эти объекты, а значит не сможет их уничтожить ;) В упомянутой книжке написано как это реализовать.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение v04bvs »

Zeus писал(а):
17.11.2007 12:27
Я по образованию - СЦБист (это - железнодорожная автоматика).
СЦБисты все помешаны на безопасности.
И если бы она достигалась только организационными методами (лишением премии), то у нас бы каждую неделю поезда под откос летали.
В ж/д автоматике безопасность достигается специальными техническими средствами и приёмами.
Человеческий фактор, ясное дело, до конца не устранишь, но как только появляется техническое решение, которое может его снизить и которое может пройти сертификацию на безопасность - оно применяется.
Вот и в программировании: чем грозить программисту пальчиком - я лучше не дам ему сделать что-то некорректное.

В данном случае способ один - смена языка программирования. С++ по определению не надежный язык. Вам подойдёт язык вроде Java или Ada.
Совет, конечно, насколько верен, настолько и бессмысленен, это я тоже понимаю :) На С++ от хорошей жизни не пишут - куча старого кода и всё такое. Могу только посочувствовать.

Zeus писал(а):
16.11.2007 23:20
Задача
Именно, что "как". Это-то довольно просто - с теме об этом уже написано.

Значит формулируйте мысли правильно, мы ведь не филологи какие. Указатель это MyClass* и не иначе. И здесь именно - что никак.
Если используются умные указатели - то вся тема выглядит попыткой изобрести один большой квадратный велосипед. Чем вас не устроил, скажем boost::shared_ptr ?

PS перечитал тему, создалось впечатление, что вы не до конца понимаете, что такое умные указатели и почему их не удаляют. Перечитайте Как "вынудить" программиста юзать "смарт-указатель"? и http://www.boost.org/libs/smart_ptr/ (в идеале и Александреску, но не обязательно), если я прав.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение Zeus »

sergio писал(а):
17.11.2007 14:30
Ну, маленькое формальное уточнение: это не просто метод, а метод для которого жестко задан прототип, и который не должен кидать исключения. )))

Хм... надо же - первый раз слышу.
Наверное я ещё до этого места в книге не дочитал :)

drBatty писал(а):
17.11.2007 15:52
Zeus писал(а):
17.11.2007 12:27
Именно, что "как". Это-то довольно просто - с теме об этом уже написано.

это просто пока у тебя 3 глобальных переменных типа int, и всё. А обратная раскрутка стека и вызов всех деструкторов после исключения - очень сложная вещь, особенно если есть недобитые объекты.

Хм... а зачем их тогда использовать - недобитые эти объекты? :unsure:
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение sergio »

Zeus писал(а):
17.11.2007 18:01
sergio писал(а):
17.11.2007 14:30
Ну, маленькое формальное уточнение: это не просто метод, а метод для которого жестко задан прототип, и который не должен кидать исключения. )))

Хм... надо же - первый раз слышу.
Наверное я ещё до этого места в книге не дочитал :)

Когда летит исключение - раскручивается стэк и удляются стэковые объекты. При этом вызываются их деструкторы. Если во время обработки активного исключения предпринимается попытка выкинуть еще одно - это скорее всего приводит к terminate. Обработка более одного исключения одновременно инфраструктурой языка не гарантируется.
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Как "вынудить" программиста юзать "смарт-указатель"?

Сообщение v04bvs »

sergio писал(а):
17.11.2007 18:08
Zeus писал(а):
17.11.2007 18:01
sergio писал(а):
17.11.2007 14:30
Ну, маленькое формальное уточнение: это не просто метод, а метод для которого жестко задан прототип, и который не должен кидать исключения. )))

Хм... надо же - первый раз слышу.
Наверное я ещё до этого места в книге не дочитал :)

Когда летит исключение - раскручивается стэк и удляются стэковые объекты. При этом вызываются их деструкторы. Если во время обработки активного исключения предпринимается попытка выкинуть еще одно - это скорее всего приводит к terminate. Обработка более одного исключения одновременно инфраструктурой языка не гарантируется.




Так что, ещё более формально, деструктор кидать исключение таки может :) Но за это надо чего-нибудь отрывать :)
Кстати, АФАИК, terminate вызывается не скорее всего, а просто вызывается. Т.е. тут всё детерминировано. Но это, опять же, АФАИК.
Спасибо сказали: