0

When I run the code:

#include <iostream>
#include <vector>

using namespace std;

struct A_s {
    int *arr;
    unsigned int l;

    A_s(unsigned int size) : l(size) {
        arr = new int[size];
        cout<<'\t'<<arr<<endl;
    }

    ~A_s() {
        delete[] arr;               // works if line is removed
    }
};

vector<A_s> vec;

int main() {
    cout<<"vec 0"<<endl;
    vec.emplace_back(1);

    cout<<"vec 1"<<endl;
    vec.emplace_back(1);

    cout<<"vec 2"<<endl;
    vec.emplace_back(1);

    for(unsigned int i = 0; i < vec.size(); i++) cout<<&vec[i]<<endl;

    cout<<"end"<<endl;
    return 0;
}

The output is:

vec 0
        0x761710
vec 1
        0x761a90
vec 2
        0x761ab0
mingw32-make: *** [Makefile:6: run] Error -1073740940

The program runs without errors if I delete the line delete[] arr. Is the destructor being called before the end of the program? And even if it does, why is it causing an error?

Roy Varon
  • 536
  • 2
  • 5
  • 14
  • `vector` does a lot of copying and destroying of copies as it resizes and shuffles entries around. This results in the Rule of Three violation coming into play. – user4581301 Jan 09 '19 at 21:48
  • *C++ weird behavior...* -- No, not weird. – PaulMcKenzie Jan 09 '19 at 21:50
  • Hint: add `A_s(A_s &&) { cout << "Move!!" << endl; }` and see what happens. – Stephan Lechner Jan 09 '19 at 21:51
  • `emplace_back` may well involve copies. If `emplace_back` has to enlarge the vector, *existing* entries are copied if the type is not movable. – zneak Jan 09 '19 at 21:51
  • `vec 0 0x1e1710 vec 1 0x1e1a90 Move!! vec 2 0x1e1ab0 Move!! Move!! mingw32-make: *** [Makefile:6: run] Error -1073740940` So I guess it does move objects... – Roy Varon Jan 09 '19 at 21:52
  • @RoyVaron Regarding your edit, it *is* a duplicate. Vector also moves elements around when it grows, which is where the rule of 3 comes into play. Another fix would be to `reserve` so it never grows, but you're better off to obey the rule of 3/5/0. – François Andrieux Jan 09 '19 at 21:53
  • 1
    I understand. Since it does move objects I have changed the vector to `vecotr`. I will remove the EDIT. Thank you everyone for the help! – Roy Varon Jan 09 '19 at 21:55
  • 2
    @RoyVaron Regardless of whether you're using vector now and emplace_back, you should at least make your classes have correct copy semantics. – PaulMcKenzie Jan 09 '19 at 21:56
  • `vector` is one of the worst things you can do because 1) you now pick up a buttload of memory management that `vector` could be doing for you and 2) You may accidentally copy elsewhere and find yourself back in this hole. The right solution is to support the [Rule of Five](https://en.cppreference.com/w/cpp/language/rule_of_three). In this case it looks like you do not want to ever copy, so you `delete` the copy constructor and assignment operator to block any copying. [Example](https://ideone.com/hxe8PV) – user4581301 Jan 09 '19 at 23:03
  • 1
    Either make `A_s` have correct copy semantics, or `delete` those functions that allow copying so that the compiler can flag any copy usage. Having a broken class floating around in your app, and hoping it isn't being used in a copying situation is not the way to address the problem. – PaulMcKenzie Jan 10 '19 at 12:26

0 Answers0