【问题标题】:c++ code compiles without errors but gives a `Segmentation fault` while runningc++ 代码编译时没有错误,但在运行时会出现“分段错误”
【发布时间】:2015-06-19 23:27:57
【问题描述】:

我无法理解我的问题。我有文件:

/* main.C */

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

using namespace std;

int main()
{
    Point p_default;
    p_default.print();

    Point p_equal(2.5);
    p_equal.print();

    Point p_full(1.23, 2.4, 0.18);
    p_full.print();

    return 0;
}

/* point.h */

#include <iostream>

using namespace std;

class Point {
    double x, y, z;
    double* arr;

public:
    // constructors
    Point (); // default
    Point (double); // equal arguments 
    Point (double _x, double _y, double _z); // standard

    // destructor
    ~Point ();

    // print function
    void print () const;
};

/* point.C */

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

using namespace std;

// constructors
Point::Point () : Point(0.0) {}; // default - zero initialised
Point::Point (double _c) : Point(_c, _c, _c) {}; // equal arguments 

// standard constructor
Point::Point (double _x, double _y, double _z = 0.0)
: x(_x), y(_y), z(_z) {
    double* arr = nullptr;

    arr = new double[3];

    *arr = x;
    *(arr + 1) = y;
    *(arr + 2) = z;
};

// destructor
Point::~Point () {
    delete[] arr;
};

// print function
void Point::print () const {
    cout << "Point(" << x << ", " << y << ", " << z << ")" << endl;
};

我使用以下命令编译我的项目:g++ -Wall -std=c++11 main.C point.C -o main。它编译时没有任何错误或警告,但是当我使用./main 运行它时,它会正确打印所有内容,最后给我Segmentation fault

Point(0, 0, 0)
Point(2.5, 2.5, 2.5)
Point(1.23, 2.4, 0.18)
Segmentation fault (core dumped)

我认为它与我的析构函数有关,但无法理解问题出在哪里。

【问题讨论】:

  • 你为什么需要arr?即使是这样,也应该是std::array&lt;double,3&gt; arr;
  • @πάνταῥεῖ 因为Point 是一个数组。
  • 使用所有警告和调试信息 (g++ -Wall -Wextra -std=c++11 -g main.C point.C -o main) 进行编译,然后使用调试器 (gdb) 和valgrind(如果有)。对于最近的 GCC,还可以考虑将 -fsanitize=address 传递给 g++
  • 您忘记了Point 需要的复制构造函数和赋值运算符。
  • @Alexandr 如果您坚持自己管理内存(恕我直言,这是一个有点愚蠢的决定),您还应该在默认构造函数中将arr 初始化为nullptr,其中包括正确处理复制构造和任务。

标签: c++ constructor segmentation-fault destructor


【解决方案1】:

问题是,您从不初始化 Point 类的数据成员“arr”。

double* arr = nullptr;

arr = new double[3];

在您的构造函数中创建一个本地指针“arr”并初始化本地指针,而不是您的类成员“arr”。 当您尝试删除析构函数中的“arr”时,您会尝试删除您的类的“arr”,它从未被分配和初始化。

【讨论】:

  • 这不是该课程的唯一问题,但很好发现,是的。
【解决方案2】:
// standard constructor
Point::Point (double _x, double _y, double _z = 0.0)
: x(_x), y(_y), z(_z) {
    // This is local, yet you are deleting the non-initialized member
    // in your destructor!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    double* arr = nullptr;

    arr = new double[3];

    *arr = x;
    *(arr + 1) = y;
    *(arr + 2) = z;
};

在代码中查看我的评论...

除此之外,您的代码还有很多问题:

  • 默认的复制构造函数是不够的。
  • 下划线作为为标准保留的前缀。
  • 使用标准容器(例如向量或数组)而不是尝试管理 记住自己。
  • 为什么首先要有一个数组?成员变量 x,y,z 还不够好吗?

问候,维尔纳

【讨论】:

  • 他甚至不需要容器。只需简单的数组就足够了。此外,他可能希望能够通过索引和名称访问成员,这通常是工会的工作。这是“arr”变量的唯一解释(我能想到的)。
猜你喜欢
  • 2020-07-04
  • 1970-01-01
  • 2022-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多