为什么在正确编译c ++类构造函数后发生运行时错误

时间:2018-02-05 05:13:13

标签: c++

当我运行./out时,它会抛出错误通知:

[1]    66798 segmentation fault  ./a.out

但它可以无错误地传递编译器:

clang++ -std=c++11 -g test.cpp

像这样的代码,我发现它在hobby->push_back(hb)附近被gdb打破了。

#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

struct X {
public:
    X(const string &, const unsigned, const string &);
    X(const X &);
    X &operator=(const X &);
    ~X();
    void print();
private:
    string name;
    unsigned age;
    shared_ptr<vector<string>> hobby;
};

X::X(const string &nm, const unsigned ae, const string &hb):
    name(nm), age(ae)
{
    hobby->push_back(hb);
    cout << "X()" << endl;
}

X::X(const X &obj)
{
    cout << "X(const X &obj)" << endl;
}

X &X::operator=(const X &obj)
{
    cout << "X::operator=(const X &obj)" << endl;
    return *this;
}

X::~X()
{
    cout << "~X()" << endl;
}

void X::print()
{
    cout << "name: " << name << '\n'
        << "age: " << age << '\n';
    for (auto const &hb : *hobby) {
        cout << hb << ' ';
    }
    cout << endl;
}

int main()
{
    X a = ("bjcharles", 30, "swimming");
    a.print();

    return 0;
}

1 个答案:

答案 0 :(得分:5)

你有一个共享指针:

shared_ptr<vector<string>> hobby;

您可以通过以下方式取消引用:

hobby->push_back(hb);

这是未定义的行为,因为您从未将shared_ptr的实例分配给std::vector,因此您可能取消引用null指针。未定义的行为意味着任何可能发生的事情,包括它的工作或在您的情况下,分段错误。

您需要:

  1. 创建内存,最好在初始化列表下的构造函数中:

    X::X(const X &obj) : hobby(std::make_shared<std::vector<...( ...

  2. 不要使用smart_ptr。 std::vector已经是一个很棒的RAII类型。除非你需要分享这个指针(你的类定义中你没有),然后直接使用std::vector(没有包围shared_ptr)就可以了。

  3. 作为最后一点,这应该可以帮助您意识到您不能依赖编译器来检查您的代码。仅仅因为编译的东西并不意味着它会起作用。例如,这将编译:

    int arr[5];
    arr[6] = 5;
    

    但这绝不意味着这是正确或安全的,并且不会导致运行时错误。它只意味着它编译。<​​/ p>