Действительно ли безопасно удалить пустой указатель?

Один из способов сделать это - получить видео с YouTube, как показано здесь

. Затем извлечь заголовок из канала атома, отправленного YouTube. Пример подачи материала показан здесь

87
задан An̲̳̳drew 2 June 2009 в 20:47
поделиться

9 ответов

Это зависит от "сейфа". Обычно это срабатывает, потому что информация хранится вместе с указателем о самом выделении, поэтому освободитель может вернуть ее в нужное место. В этом смысле это «безопасно», если ваш распределитель использует внутренние граничные теги. (Многие делают.)

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

Нет веской причины делать то, что вы делаете, так, как вы это делаете. Если вы хотите написать свои собственные функции освобождения, вы можете использовать шаблоны функций для создания функций с правильным типом. Хорошая причина для этого - создать распределители пула, которые могут быть чрезвычайно эффективными для определенных типов.

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

22
ответ дан 24 November 2019 в 07:43
поделиться

Если вам нужен только буфер, используйте malloc / free. Если вы должны использовать new / delete, рассмотрите тривиальный класс-оболочку:

template<int size_ > struct size_buffer { 
  char data_[ size_]; 
  operator void*() { return (void*)&data_; }
};

typedef sized_buffer<100> OpaqueBuffer; // logical description of your sized buffer

OpaqueBuffer* ptr = new OpaqueBuffer();

delete ptr;
0
ответ дан 24 November 2019 в 07:43
поделиться

Если вы действительно должны это сделать, почему бы не вырезать среднего человека (операторы new и delete ) и не вызвать глобальный оператор new и оператор удалить напрямую? (Конечно, если вы пытаетесь инструментировать операторы new и delete , вам действительно следует заново реализовать оператор new и оператор delete ].)

void* my_alloc (size_t size)
{
   return ::operator new(size);
}

void my_free (void* ptr)
{
   ::operator delete(ptr);
}

Обратите внимание, что в отличие от malloc () , оператор new выбрасывает std :: bad_alloc при ошибке (или вызывает new_handler ], если он зарегистрирован).

5
ответ дан 24 November 2019 в 07:43
поделиться

Многие люди уже прокомментировали, что нет, удалять указатель void небезопасно. Я согласен с этим, но я также хотел добавить, что если вы работаете с указателями void для выделения смежных массивов или чего-то подобного, вы можете сделать это с помощью new , чтобы вы могли для безопасного использования delete (с, кхм, небольшой дополнительной работой). Это делается путем выделения пустого указателя на область памяти (называемую «ареной»), а затем передачи указателя на арену в new. См. Этот раздел в FAQ по C ++ . Это общий подход к реализации пулов памяти в C ++.

5
ответ дан 24 November 2019 в 07:43
поделиться

Потому что char не имеет специальной логики деструктора. ЭТО не сработает.

class foo
{
   ~foo() { printf("huzza"); }
}

main()
{
   foo * myFoo = new foo();
   delete ((void*)foo);
}

В д'ектор не позвонят.

5
ответ дан 24 November 2019 в 07:43
поделиться

Удаление указателя void опасно, потому что деструкторы не будут вызываться для значения, на которое он фактически указывает. Это может привести к утечке памяти / ресурсов в вашем приложении.

13
ответ дан 24 November 2019 в 07:43
поделиться

Это плохая идея и не то, что вы бы сделали на C ++. Вы теряете информацию о типе без причины.

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

Вместо этого вам следует переопределить new / delete.

Удаление void *, вероятно, случайно освободит вашу память правильно, но это неправильно, потому что результаты не определены.

Если по какой-то неизвестной мне причине вам нужно сохранить ваш указатель в пустоте *, затем освободите его, вы должны использовать malloc и free.

24
ответ дан 24 November 2019 в 07:43
поделиться

Удаление с помощью указателя void не определено стандартом C ++ - см. Раздел 5.3.5 / 3:

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

И его сноска:

Это означает, что объект не может быть удаляется с помощью указателя типа void * потому что нет объектов типа void

.

138
ответ дан 24 November 2019 в 07:43
поделиться

Если вы хотите использовать void *, почему бы вам не использовать только malloc / free? new / delete - это больше, чем просто управление памятью. По сути, new / delete вызывает конструктор / деструктор, и происходит еще кое-что. Если вы просто используете встроенные типы (например, char *) и удалите их через void *, это сработает, но все же это не рекомендуется. Суть в том, чтобы использовать malloc / free, если вы хотите использовать void *. В противном случае вы можете использовать шаблонные функции для вашего удобства.

template<typename T>
T* my_alloc (size_t size)
{
   return new T [size];
}

template<typename T>
void my_free (T* ptr)
{
   delete [] ptr;
}

int main(void)
{
    char* pChar = my_alloc<char>(10);
    my_free(pChar);
}
5
ответ дан 24 November 2019 в 07:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: