Безопасное удаление в C ++ - PullRequest
0 голосов
/ 12 июля 2020

Мой вопрос не в том, как создать эту функцию с нуля, а в том, можно ли использовать мою реализацию.

У меня есть следующие классы:

    class PointerStorage
    {
    private:
        static std::mutex m;
        static std::unordered_set<void*> pointers;
    public:
        static inline void add(void* ptr){
            m.lock();
            PointerStorage::pointers.insert(ptr);
            m.unlock();
        }
        static inline bool tryRemove(void* ptr) {
            std::lock_guard<std::mutex> g(m);
            return PointerStorage::pointers.erase(ptr);
        }
        static inline bool hasPtr(void* ptr) {
            std::lock_guard<std::mutex> g(m);
            return PointerStorage::pointers.find(ptr) != PointerStorage::pointers.end();
        }
    };
    class Deletable
    {
    public:
        void* operator new(size_t size) {
            void* p = malloc(size);
            PointerStorage::add(p);
            return p;
        }
        void operator delete(void* ptr) {
            if (PointerStorage::tryRemove(ptr)) {
                free(ptr);
            }
        }
    };

Моя идея наследовать от Deletable при необходимости и использовать операторы

Но мне интересно, возможна ли такая ситуация:

  • Создаю объект в переменной OBJ, удаляю
  • Я создаю новый объект в другой переменной, его адрес становится таким же, как в OBJ, а операция удаления OBJ влияет на мой новый объект.

1 Ответ

2 голосов
/ 12 июля 2020

Обычно вы не должны предполагать, что указатель, использованный для старого объекта, не используется повторно для нового объекта.

Иногда вы захотите сделать такое предположение.

Для многопоточного программирует эту ситуацию, когда вы хотите быть уверенным, что указатель не используется повторно, это проблема ABA. Проще говоря, эта проблема возникает, когда вы выполняете сравнение-обмен старого указателя с новым указателем, но вы не можете быть уверены, что старый указатель действительно является старым указателем.

Одно из решений в основном состоит в том, чтобы сохранить старый указатель в течение некоторого времени, это называется указатель опасности .

Другое - полагаться не только на значение указателя, но и на счетчик (хотя счетчик все еще может оборачиваться, вероятность отказа ниже).

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

...