Вызов delete для двух указателей на один и тот же объект - PullRequest
5 голосов
/ 14 июля 2010

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

Я написал код так, чтобы события помещались в стек ( стек , как в структуре, созданной пользователем; сами события распределяются с использованием new) и delete d после их информации. читается и действует. Это вызывает у меня некоторые проблемы, потому что в одном случае событие отправляется по цепочке из трех обработчиков. Скажем, HandlerA отправляет new Event в HandlerB, который помещает его в стек и читает его, отправляя в HandlerC, который читает его и выполняет все, что ему нужно для выполнения, после чего delete s указатель события и устанавливает его на NULL. Теперь мы возвращаемся к HandlerB и, ну, он также хочет delete и NULL указатель на событие. Но указатель является локальной переменной, и он в итоге удаляет один и тот же адрес дважды, что приводит к исключению.

Как вы обходите это? Вам нужно использовать один из этих причудливых auto_ptr (здесь еще рано учиться), или я здесь упускаю что-то фундаментальное?

Ответы [ 3 ]

10 голосов
/ 14 июля 2010

Я написал код так, чтобы события помещались в стек и удалялись после того, как их информация прочитана и обработана.

Здесь есть некоторая путаница - объекты в стеке должны , а не быть delete d.Объекты, созданные с помощью new (в куче), должны.

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

Вы также можете использовать boost::shared_ptr (он может быть доступен также как std::tr1::shared_ptr, в зависимости от вашего компилятора) вместо необработанных указателей.Это сохраняет количество ссылок на объект и delete s, когда количество ссылок падает до 0.

6 голосов
/ 14 июля 2010

То, что вы хотите, это некоторая оболочка указателя, которая для экземпляров использует подсчет ссылок, чтобы проверить, ссылаются ли другие переменные на тот же экземпляр. Идея состоит в том, что объект, на который указывает указатель, освобождается только тогда, когда этот объект не используется каким-либо другим указателем. Такие указатели обычно называются Smart Pointers . В c ++ вы можете использовать, например, те, которые предоставляются Boost .

1 голос
/ 14 июля 2010

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

Это сказал; если вы хотите потратить время на их изучение, я думаю, что решение Smart Pointer, вероятно, лучше!

...