0

After I run the program I get an error saying projectname has triggered a breakpoint. I still do not know what the error is. I think there's a member function missing but someone help me out?

#include "AClass.h"
#include <iostream>

using namespace std;

int main()
{
    AClass* x = new AClass(10, -1.0);
    AClass y = *x;
    delete x;
    return 0;
}

Code from my cpp file is as follows:

#include "AClass.h"
#include <iostream>
using namespace std;

// Constructor
AClass::AClass(int len, double val)
    : length(len)
{
    if (len < 0) {
        cout << "Invalid data length = " << len << endl;
        data = NULL;
    }

    else {
        data = new double[length];
        for (int i = 0; i < length; i++)
            data[i] = val;
    }
}

// Destructor
AClass::~AClass()
{
    // delete data if it is not NULL
    if (data) delete[] data;
}
Venom2901
  • 19
  • 1
  • 4
  • Triggering a breakpoint doesn't sound like an error; how are you being informed of this? – Scott Hunter Oct 30 '19 at 19:02
  • Have you tried running it in your debugger? What did you learn when doing so? – Jesper Juhl Oct 30 '19 at 19:03
  • A breakpoint most likely means that you've clicked on a dot on the left hand margin in your editor which tells the debugger to pause execution there. Either that or its a exception breakpoint in which case double check the message to see what the underlying error was. In either case, the breakpoint isn't an error. Check the left hand margin next to the code to see if there's any dots there which indicate a breakpoint. – Carcigenicate Oct 30 '19 at 19:05
  • 2
    Looks like you have a [Rule of Three](https://en.cppreference.com/w/cpp/language/rule_of_three) violation. Need a [mcve] to confirm. – user4581301 Oct 30 '19 at 19:06
  • 2
    Breakpoints are also triggered when your program does something that really upsets the system and will lead to a crash. The debugger halts at the site of the crash and allows you to perform a postmortem. The aftermath of a Rule of Three violation often is a crash., – user4581301 Oct 30 '19 at 19:08
  • 1
    Random comments on your code: 1) `data = NULL;` - No. Please use `nullptr` in new code (and update old code). 2) `if (data) delete[] data;` - No. That conditional is completely pointless, `delete[]()` can handle being passed `nullptr`, it is a no-op. Get rid of the pointless `if`. 3) Why are you doing manual memory management in C++ code written in 2019 that is not implementing the guts of a container or similar? Use `std::array`, `std::vector` or some other appropriate container, or *at least* use smart pointers - naked `new`/`delete` is a code smell. – Jesper Juhl Oct 30 '19 at 19:10
  • 3
    *I still do not know what the error is.* -- Put a breakpoint in your destructor. Watch that same pointer value `data` being deleted twice. Double deletion error, crash. – PaulMcKenzie Oct 30 '19 at 19:12

1 Answers1

3

Your AClass member double* data; will be copied here:

AClass y = *x;

Since you haven't provided copy/move constructors/assignment operators, the raw pointer will be copied as-is in these situations and delete[] data will be done by both x and y in the destructor.

Mandatory read when dealing with raw pointers: https://en.cppreference.com/w/cpp/language/rule_of_three

And these:
What is The Rule of Three?
Rule-of-Three becomes Rule-of-Five with C++11?

Here's an example implementation of the member functions mentioned in the above articles. It's a little much - and error prone, which is why it's almost always better to use a standard container.

#include <algorithm>
#include <iostream>
#include <utility>

class AClass {
public:
    AClass(size_t len, double val);

    // rule of five:
    AClass(const AClass& rhs);            // copy constructor
    AClass(AClass&& rhs);                 // move constructor
    AClass& operator=(const AClass& rhs); // copy assignment
    AClass& operator=(AClass&& rhs);      // move assignment
    ~AClass();

private:
    size_t length; // use an unsigned type since you only accept unsigned values
    double* data;
};

// destructor
AClass::~AClass() {
    delete[] data;
}

AClass::AClass(size_t len, double val) : 
    length(len),
    data(new double[length])
{
    std::fill_n(data, length, val);
}

// copy constructor
AClass::AClass(const AClass& rhs) :
    length(rhs.length),
    data(new double[length])
{
    std::copy_n(rhs.data, length, data);
}

// move constructor
AClass::AClass(AClass&& rhs) :
    length(std::exchange(rhs.length, 0)),
    data(std::exchange(rhs.data, nullptr))
{}

// copy assignment
AClass& AClass::operator=(const AClass& rhs) {
    double* tmpdata = new double[rhs.length];
    delete[] data;
    length = rhs.length;
    data = tmpdata;
    std::copy_n(rhs.data, length, data);
    return *this;
}

// move assignment
AClass& AClass::operator=(AClass&& rhs) {
    // leave the destruction up to the moved-from object
    std::swap(length, rhs.length);
    std::swap(data, rhs.data);
    return *this;
}

int main() {
    AClass* x = new AClass(10, -1.0);
    AClass y = *x;
    delete x;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • 1
    The one you really want is [What is The Rule of Three?](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). That said, this would be the duplicate if A) you're right and B) this question was complete enough to provide a concrete answer – user4581301 Oct 30 '19 at 19:13
  • @user4581301 True... perhaps better to remove the answer and close as a dupe once it's confirmed? ... or I can add example ctors/assignment operators for this specific case? – Ted Lyngmo Oct 30 '19 at 19:16