1

Will delete free the right amount of bytes ?

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; 
kometen
  • 6,536
  • 6
  • 41
  • 51
  • 1
    Please note that you're deleting a smart pointer. It will be deleted again resulting in undefined behavior. At that point the right about of bytes might be freed. Or your computer might fly away. – Bas in het Veld Jun 07 '21 at 10:14
  • 7
    @BasinhetVeld That's not correct. Please see [`std::unique_ptr::release`](https://en.cppreference.com/w/cpp/memory/unique_ptr/release). – G.M. Jun 07 '21 at 10:16
  • 1
    That will absolutely NOT delete the right amount of bytes (if `sockaddr` and `sockaddr_in` are not the same size) and also will NEVER (even if they are the same size) call the right destructor. – perivesta Jun 07 '21 at 10:18
  • 3
    You are initially using RAII but then dropping that, using reinterpret_cast and cleaning the new object up using a different deleter. How do you expect this would be safe in any way?? – JHBonarius Jun 07 '21 at 10:20
  • It might do anything. You are firmly into undefined behaviour here. There is no reason to write code like this. Don't. – user207421 Jun 07 '21 at 10:33
  • What if i cast it to a void pointer ? In C with malloc and free it will work because on the beginning of the allocated space, there is a header with the information of the number of bytes allocated so free(void *) knows how many bytes to free. I don't need to call a destructor for these structs, because they have no constructor respectively a default-constructor. – Markus Fischer Jun 07 '21 at 10:33
  • @G.M. I didn't read properly. Sorry about that. – Bas in het Veld Jun 07 '21 at 15:34
  • @MarkusFischer they soul e aggregate type which is stricter requirement, but in this case they are – Swift - Friday Pie Jun 18 '21 at 09:32

2 Answers2

4

In most cases, sockaddr is not a base class of sockaddr_in (source 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];
};

Therefore according to [expr.delete]/p3 the behavior of the program is undefined:

... if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.


With that said, in many cases the built-in operator delete simply delegates to free, which does not need the size, and the program will appear to work as intended (though when coding in C++ we really prefer to stay in the realm of defined behavior).

Why not simply let the unique_ptr do its job and delete the sockaddr_in upon destruction?

rustyx
  • 80,671
  • 25
  • 200
  • 267
1

It would delete sizeof(sockaddr) bytes , unless sockaddr is base type of sockaddr_in and got a virtual destructor. Wherever that would succeed otherwise or not is undefined. After you did reinterpret_cast, sockaddr* is the static type of pointer. question is , does it have different dynamic type or not.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42