Удалить и бросить. Будет удалять бесплатно нужное количество байт?

Удалит ли бесплатно нужное количество байт?

unique_ptr<sockaddr_in> up = make_unique<sockaddr_in>();        
// or unique_ptr<sockaddr_in> up( new sockaddr_in ); ???

/* 
    Some stuff 
    sockaddr and sockaddr_in are two different types of struct and are not relateted 
*/

sockaddr *p = reinterpret_cast<sockaddr *>( up.release() );

delete p; 

person Markus Fischer    schedule 07.06.2021    source источник
comment
Обратите внимание, что вы удаляете умный указатель. Он будет снова удален, что приведет к неопределенному поведению. В этот момент право на количество байтов может быть освобождено. Или ваш компьютер может улететь.   -  person Bas in het Veld    schedule 07.06.2021
comment
@BasinhetVeld Это неправильно. См. std::unique_ptr::release.   -  person G.M.    schedule 07.06.2021
comment
Это абсолютно НЕ удалит нужное количество байтов (если sockaddr и sockaddr_in не одного размера), а также НИКОГДА (даже если они одного размера) вызовет правильный деструктор.   -  person dave    schedule 07.06.2021
comment
Сначала вы используете RAII, но затем отбрасываете его, используя reinterpret_cast и очищаете новый объект с помощью другого удаления. Как вы ожидаете, что это будет безопасно в любом случае ??   -  person JHBonarius    schedule 07.06.2021
comment
Это может сделать что угодно. Здесь вы твердо придерживаетесь неопределенного поведения. Нет причин писать такой код. Не.   -  person user207421    schedule 07.06.2021
comment
Что, если я приведу его к пустому указателю? В C с malloc и free это будет работать, потому что в начале выделенного пространства есть заголовок с информацией о количестве выделенных байтов, поэтому free(void *) знает, сколько байтов нужно освободить. Мне не нужно вызывать деструктор для этих структур, потому что у них нет конструктора соответственно конструктора по умолчанию.   -  person Markus Fischer    schedule 07.06.2021
comment
@G.M. Я не правильно прочитал. Прости за это.   -  person Bas in het Veld    schedule 07.06.2021
comment
@MarkusFischer у них есть совокупный тип, который является более строгим требованием, но в этом случае они   -  person Swift - Friday Pie    schedule 18.06.2021


Ответы (2)


В большинстве случаев sockaddr не является базовым классом sockaddr_in (источник 1, 2, 3):

struct sockaddr {
        ushort  sa_family;
        char    sa_data[14];
};

struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};

Поэтому в соответствии с [expr.delete]/p3 поведение программы undefined:

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


При этом во многих случаях встроенный оператор delete просто делегирует free, которому не нужен размер, и программа будет работать так, как задумано (хотя при кодировании на C++ мы действительно предпочитаем оставаться в сфере определенного поведения).

Почему бы просто не позволить unique_ptr делать свою работу, а delete - sockaddr_in после уничтожения?

person rustyx    schedule 07.06.2021

Он удалит sizeof(sockaddr) байт, если только sockaddr не является базовым типом sockaddr_in и не получил виртуальный деструктор. Везде, где это было бы успешным в противном случае или нет, не определено. После того, как вы сделали reinterpret_cast, sockaddr* является статическим типом указателя. вопрос в том, имеет ли он другой динамический тип или нет.

person Swift - Friday Pie    schedule 07.06.2021