2

Here I am creating dynamically allocated array of S objects and I expect them to be destroyed by unique_ptr, which doesn't happen and I get this error

Command terminated by signal 11

and that means the program accessed memory which it shouldn't have accessed as far as I am concerned.

#include <iostream>
#include <memory>

class S{
    public:
        S(){std::cout<<"Constructor\n";}
        ~S(){std::cout<<"Destructor\n";}
};

int main() {
    S* arr=new S[4];
    {
        using namespace std;
        unique_ptr<S> ptr=unique_ptr<S>(arr);
    }
}
  • `std::unique_ptr` will assume it is managing a single object and effectively do `delete arr`. Since `arr` was initialised using an the array form of operator `new`, the behaviour is undefined. – Peter Nov 03 '20 at 13:48
  • 3
    I would recommend that you don't allocate memory manually with `new` or `new[]` and instead use `make_unique`. In this case, you should just use `auto arr = make_unique(4);` – Nikos C. Nov 03 '20 at 13:53
  • @ErikNouroyan it is similar, but answer for Nikos is exception safe and KamilCuk is not. – Marek R Nov 03 '20 at 14:57

1 Answers1

6
new s[4]

If you use new[] allocation you have to destroy it using delete[], not delete.

    auto ptr = unique_ptr<S[]>(arr);
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Thanks for your answer, can I know what happens in my case if I ommit that? I mean what happens internally? – Erik Nouroyan Nov 03 '20 at 13:42
  • `in my case if I ommit that?` Undefined behavior. `I mean what happens internally?` No idea, you'll have to read the source code of your standard library implementation. – KamilCuk Nov 03 '20 at 13:43
  • @TedLyngmo It is recommended – Erik Nouroyan Nov 03 '20 at 13:45
  • @ErikNouroyan Internally, the `unique_ptr` version is instantiated that calls `delete` in its destructor instead of `delete[]`.. Since you allocated memory using `new[]` instead of `new`, you get undefined behavior, which in this case happens to result in a signal 11 abort. – Nikos C. Nov 03 '20 at 13:46
  • @NikosC. but I don't know why it works for int[] and not S[] , I have no idea why that is so – Erik Nouroyan Nov 03 '20 at 13:46
  • @TedLyngmo Sure, it is the constructor for unique_ptr – Erik Nouroyan Nov 03 '20 at 13:47
  • 1
    @ErikNouroyan You can't really argue why something does or does not happen when you have undefined behavior. In this case, it might have something to do that `int` is a basic type and has no destructor. But really, it doesn't matter. – Nikos C. Nov 03 '20 at 13:50
  • @TedLyngmo template explicit unique_ptr( U p ) this one I guess U is replaced with S[] – Erik Nouroyan Nov 03 '20 at 13:52
  • @NikosC. alright, thanks – Erik Nouroyan Nov 03 '20 at 13:52
  • 1
    @TedLyngmo that's what is needed I guess, You take the ownership of the object and since it is of type S[] when coming out of scope the destructor for unique_ptr is called which does something similar to this delete[] – Erik Nouroyan Nov 03 '20 at 13:57
  • @ErikNouroyan Jeez ... I totally misread the whole thing (I saw `arr` as a size argument) ... sorry for the confusion. I'll delete my comments... – Ted Lyngmo Nov 03 '20 at 14:02
  • 1
    @TedLyngmo It's alright – Erik Nouroyan Nov 03 '20 at 14:03
  • This is a wrong usage. Normally, the result of `new` must be used instantly by the final owner. – Red.Wave Nov 03 '20 at 15:49