启用g ++优化会导致细分错误

时间:2016-03-22 10:38:01

标签: c++ c++11 g++

我的程序在编译时会出现分段错误:

g++ -std=c++11 iForest.cpp -o iForest -O2

我已经读过这个帖子 - Turning on g++ optimization causes segfault - I don't get it,但我认为我在那里没有提出同样的问题。我还检查了我的代码。我真的不知道哪里可能存在问题。请提供一些帮助。这是我的代码:

    #include <bits/stdc++.h>
using namespace std;

class iTree{
public:
    iTree(): root(NULL) {}
    iTree(const vector<double>& _items): items(_items){}
    iTree(const string &fname){ readData(fname); }
    ~iTree(){delete root;}

    void print(){
        for(int i = 0; i < np; ++i){
            for(int j = 0; j < nd; ++j){
                cout << items[i*nd + j] << " ";
            }
            cout << endl;
        }
    }

private:
    int height, np, nd; //np: # of points, nd: # of dimensions of a point
    vector<double> items;   // items.size() = np*nd;
    struct Node{
        double val;
        Node *left, *right;
        int attri;  // index of the attribute we pick

        Node(): val(0.0), left(NULL), right(NULL), attri(-1) {}
        ~Node(){ delete left; delete right;}
    } *root;

    void readData(const string &fname){
        ifstream ifs(fname);
        ifs >> np >> nd;

        items.resize(np*nd, 0.0);
        for(int i = 0; i < np*nd; ++i)  ifs >> items[i];
        ifs.close();
    }
};

int main(){
    iTree forest("data.dat");
    forest.print();
    return 0;
}

使用g++ -std=c++11 iForest.cpp -o iForest编译时没有生成段错误。如果我不打印,也不会产生段错误。但我不认为我的print()函数有任何错误。

如果你想运行它,我使用的是“data.dat”:

10 5
509304 9 0 2 1.0
509305 9 0 2 0.0
509306 9 0 2 0.0
509307 9 0 2 0.0
509308 9 0 2 0.0
509309 9 0 2 0.0
509310 9 0 2 0.0
509311 9 0 2 0.0
509312 9 0 2 0.0
509313 9 0 2 0.0

3 个答案:

答案 0 :(得分:7)

当您通过构造函数root(在您的示例中执行)输入时,您的类包含未初始化的变量iTree(const string &fname){ readData(fname); }。然后你的析构函数会delete root;

要解决此问题,您可以初始化root,最简单的方法是将{}放在;的声明中。

为了避免以后的错误,最好将NodeiTree声明为不可复制和不可移动,直到您准备好为它们实现复制操作。默认的复制/移动行为会因rule of three违规而导致内存错误。

答案 1 :(得分:3)

正如DeiDei在他的评论中写道,你删除了一些你没有分配的指针。我会更进一步说你应该使用聪明的指针和RAII成语来解决这些问题。 C指针经常导致一大堆问题。另外,请使用nullptr代替NULL宏。

编辑:要添加精度,请使用std::unique_ptr,该 int BlueHist; int GreenHist; int RedHist; Image<Bgr, Byte> img = new Image<Bgr, byte>(bmp); DenseHistogram Histo = new DenseHistogram(255, new RangeF(0, 255)); Image<Gray, Byte> img2Blue = img[0]; Image<Gray, Byte> img2Green = img[1]; Image<Gray, Byte> img2Red = img[2]; Histo.Calculate(new Image<Gray, Byte>[] { img2Blue }, true, null); double[] minV, maxV; Point[] minL, maxL; Histo.MinMax(out minV, out maxV, out minL, out maxL); BlueHist = maxL[0].Y; Histo.Clear(); Histo.Calculate(new Image<Gray, Byte>[] { img2Green }, true, null); Histo.MinMax(out minV, out maxV, out minL, out maxL); GreenHist = maxL[0].Y; Histo.Clear(); Histo.Calculate(new Image<Gray, Byte>[] { img2Red }, true, null); Histo.MinMax(out minV, out maxV, out minL, out maxL); RedHist = maxL[0].Y; 不可复制且仅可移动,如M.M所述。

答案 2 :(得分:3)

这是更正的程序,缩减为一个文件(数据现在是一个嵌入的字符串,使演示更容易)。

我有嵌入的解释性说明。注意关注点的分离,使用unique_ptr,因此不需要析构函数。这是转向给我自由移动语义。

// note 8: include the proper headers
#include <vector>
#include <sstream>
#include <iostream>
#include <memory>

class iTree{
public:
    iTree(): root(nullptr) {}
    iTree(const std::vector<double>& _items): items(_items){}

    // note 5: separate concerns - a tree needs to know nothing about files - only about istreams.
    iTree(std::istream & is){ readData(is); }

    // note 3: destructor now un-necessary

    void print(){
        for(int i = 0; i < np; ++i){
            for(int j = 0; j < nd; ++j){
                std::cout << items[i*nd + j] << " ";
            }
            std::cout << std::endl;
        }
    }

private:
    int height, np, nd; //np: # of points, nd: # of dimensions of a point
    std::vector<double> items;   // items.size() = np*nd;
    struct Node{
        double val;
        // note 1: unique_ptr instead of raw pointer
        std::unique_ptr<Node> left, right;
        int attri;  // index of the attribute we pick

        Node(): val(0.0), left(nullptr), right(nullptr), attri(-1) {}
        // note 4: destructor now un-necessary
    };
    // note 2: unique_ptr instead of raw pointer
    std::unique_ptr<Node> root;

    void readData(std::istream &is){
        is >> np >> nd;

        items.resize(np*nd, 0.0);
        for(int i = 0; i < np*nd; ++i)  is >> items[i];
    }
};

int main(){

    static constexpr auto data =
R"data(10 5
509304 9 0 2 1.0
509305 9 0 2 0.0
509306 9 0 2 0.0
509307 9 0 2 0.0
509308 9 0 2 0.0
509309 9 0 2 0.0
509310 9 0 2 0.0
509311 9 0 2 0.0
509312 9 0 2 0.0
509313 9 0 2 0.0
)data";

    // note 6: now I can express the entire example in one file - no need for a data file.
    std::istringstream is(data);

    // note 7: because I didnt define destuctors I now have move semantics for free
    //         which will be useful for performance and give me more expressive code.
    auto forest = iTree(is);
    forest.print();
    return 0;
}

预期产出:

509304 9 0 2 1
509305 9 0 2 0
509306 9 0 2 0
509307 9 0 2 0
509308 9 0 2 0
509309 9 0 2 0
509310 9 0 2 0
509311 9 0 2 0
509312 9 0 2 0
509313 9 0 2 0