我的程序在编译时会出现分段错误:
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
答案 0 :(得分:7)
当您通过构造函数root
(在您的示例中执行)输入时,您的类包含未初始化的变量iTree(const string &fname){ readData(fname); }
。然后你的析构函数会delete root;
要解决此问题,您可以初始化root
,最简单的方法是将{}
放在;
的声明中。
为了避免以后的错误,最好将Node
和iTree
声明为不可复制和不可移动,直到您准备好为它们实现复制操作。默认的复制/移动行为会因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