【问题标题】:How to solve error (projectname has triggered breakpoint)?如何解决错误(项目名称已触发断点)?
【发布时间】:2019-10-30 19:01:25
【问题描述】:

运行程序后,我收到一条错误消息,提示 projectname 已触发断点。我仍然不知道错误是什么。我认为缺少一个成员函数,但有人帮我吗?

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

using namespace std;

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

我的 cpp 文件中的代码如下:

#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;
}

【问题讨论】:

  • 触发断点听起来不像是错误;您是如何得知此事的?
  • 看起来您有 Rule of Three 违规行为。需要minimal reproducible example 进行确认。
  • 当你的程序做了一些真正扰乱系统并导致崩溃的事情时,也会触发断点。调试器在崩溃现场停止并允许您执行事后分析。违反三规则的后果通常是崩溃。,
  • 您的代码上的随机 cmets:1) data = NULL; - 否。请在新代码中使用 nullptr(并更新旧代码)。 2)if (data) delete[] data; - 不。那个条件完全没有意义,delete[]() 可以处理通过nullptr,这是一个空操作。摆脱毫无意义的if。 3) 你为什么要在 2019 年编写的 C++ 代码中进行手动内存管理,但没有实现容器或类似的内容?使用std::arraystd::vector 或其他适当的容器,或者至少使用智能指针 - 裸露的new/delete 是一种代码味道。
  • 我仍然不知道错误是什么。 -- 在你的析构函数中放置一个断点。观察相同的指针值data 被删除两次。双重删除错误,崩溃。

标签: c++ visual-studio member-functions


【解决方案1】:

您的AClass 成员double* data; 将被复制到这里:

AClass y = *x;

由于您没有提供复制/移动构造函数/赋值运算符,原始指针将在这些情况下按原样复制,delete[] data 将由 x 和 @ 完成987654330@ 在析构函数中。

处理原始指针时强制读取: https://en.cppreference.com/w/cpp/language/rule_of_three

还有这些:
What is The Rule of Three?
Rule-of-Three becomes Rule-of-Five with C++11?

这是上述文章中提到的成员函数的示例实现。这有点多 - 而且容易出错,这就是为什么使用标准容器几乎总是更好的原因。

#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;
}

【讨论】:

  • 你真正想要的是What is The Rule of Three?。也就是说,如果 A)你是对的并且 B)这个问题足够完整,可以提供一个具体的答案,这将是重复的
  • @user4581301 是的......也许最好删除答案并在确认后作为骗子关闭? ...或者我可以为这种特定情况添加示例 ctors/assignment 运算符?
猜你喜欢
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
相关资源
最近更新 更多