我尝试将自定义类的对象push_back到指针向量并将我的自定义类作为类型时遇到了一些麻烦。请参阅下面的代码以及收到的错误。我在Windows XP上使用带有CDT插件和OpenCV的Eclipse。
我花了很多时间试图找到答案,但无济于事! ps我是学生,指针等不是我的事!
std:: vector<RoadLine>* LaneChangeDetector::roadLines(IplImage* img_8uc1, IplImage* img_8uc3, IplImage* img_edge, std::vector <RoadLine>* roadVector){
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* lines = 0;
CvMemStorage* roadStorage = cvCreateMemStorage(0);
CvSeq* roadLines = 0;
// Probabalistic Hough transform returns line segments from edge detected image
lines = cvHoughLines2( img_edge, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 50, 200, 200 );
// Sequence roadlines, lines with correct slope are added to this sequence
roadLines = cvCreateSeq(0, lines->header_size, lines->elem_size, roadStorage);
// slope
double m = 0.0;
// Point of intersection
CvPoint poi;
for(int i = 0; i < lines->total; i++ ){
CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
CvPoint pt1 = line[0];
CvPoint pt2 = line[1];
double x1 = double(pt1.x);
double y1 = double(pt1.y);
double x2 = double(pt2.x);
double y2 = double(pt2.y);
if(pt1.x == pt2.x){
m = 1.0;
}
else{
m = (double(y2 - y1)/(double(x2 - x1)));
}
if( ((m>0.45) && (m<0.75)) || ((m<-0.45) && (m>-0.75)) ){
// If the slope is between measured parameters add to roadLines sequence for further analysis
cvSeqPush(roadLines, line);
}
}
// otherRoadLine used for comparison
CvPoint* otherRoadLine;
for(int a=0; a<roadLines->total; a++){
CvPoint* roadLine = (CvPoint*)cvGetSeqElem(roadLines,a);
CvPoint rl1 = roadLine[0];
CvPoint rl2 = roadLine[1];
int lineCount = 0;
if(a>0){
// Test the current line against all the previous lines in the sequence.
// If the current line is far enough away from all other lines then draw it
for(int b=0; b<a; b++){
otherRoadLine = (CvPoint*)cvGetSeqElem(roadLines,b);
if((roadLine->x > ((otherRoadLine->x) + 200)) || (roadLine->x < ((otherRoadLine->x) - 200)) ){
lineCount++;
}
}
if(lineCount == a){
cvLine(img_final, roadLine[0], roadLine[1], CV_RGB(0,0,255), 3, CV_AA, 0 );
RoadLine myLine = RoadLine(roadLine, 1);
roadVector->push_back(myLine); //ERROR OCCURS HERE
cvShowImage("Plate Detection", img_final);
cvWaitKey(0);
}
}
else{
cvLine(img_final, roadLine[0], roadLine[1], CV_RGB(0,0,255), 3, CV_AA, 0 );
RoadLine myLine = RoadLine(roadLine, 1);
roadVector->push_back(myLine //ERROR OCCURS HERE
cvShowImage("Plate Detection", img_final);
cvWaitKey(0);
}
}
if(roadVector->size() >= 2){
int pos = 0;
RoadLine line1 = roadVector->at(pos);
RoadLine line2 = roadVector->at(pos + 1);
CvPoint* A = line1.line;
CvPoint p1 = A[0];
CvPoint p2 = A[1];
int A1 = p1.y - p2.y;
int B1 = p1.x - p2.x;
int C1 = (p1.x*p2.y) - (p1.y*p2.x);
CvPoint* B = line2.line;
CvPoint p3 = B[0];
CvPoint p4 = B[1];
int A2 = p3.y - p4.y;
int B2 = p3.x - p4.x;
int C2 = (p3.x*p4.y) - (p3.y*p4.x);
int det = A2*B1 - A1*B2;
if(det == 0){
printf("Lines are parallel");
}
else{
int x = ( C1*(p3.x - p4.x) - (p1.x - p2.x)*C2 )/det;
int y = ( C1*(p3.y - p4.y) - (p1.y - p2.y)*C2 )/det;
poi.x = x;
poi.y = y;
horizon = poi.x;
cvCircle(img_final, poi, 10, CV_RGB(255, 0, 0), 2, CV_AA, 0);
}
}
cvShowImage("Plate Detection", img_final);
cvWaitKey(0);
return roadVector;
}
可以在此处看到自定义类RoadLine
#include <cv.h>
class RoadLine{
private:
CvPoint* line;
int lane;
public:
RoadLine(CvPoint*, int);
};
RoadLine::RoadLine(CvPoint* aLine, int aLane){
line = aLine;
lane = aLane;
}
从调试中我可以看到“std :: vector&lt; RoadLine&gt; * roadVector”正在初始化。
以下是Eclipse告诉我的内容:
3 std::vector<RoadLine, std::allocator<RoadLine> >::push_back() F:\MinGW\include\c++\3.4.5\bits\stl_vector.h:560 0x0043e3f9
4 void std::_Construct<RoadLine, RoadLine>() F:\MinGW\include\c++\3.4.5\bits\stl_construct.h:81 0x0044015d
程序跳转到stl_construct.h中的这段代码
template<typename _T1, typename _T2>
inline void
_Construct(_T1* __p, const _T2& __value)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 402. wrong new expression in [some_]allocator::construct
::new(static_cast<void*>(__p)) _T1(__value); //DEBUG THROWS ME TO THIS LINE
}
再次感谢任何帮助。
干杯
专利
答案 0 :(得分:4)
您不使用指针向量,而是使用对象向量。在这种情况下,您的类需要一个复制构造函数,因为push_back存储了一个对象的副本。
作为一般调试建议,尝试通过删除尽可能多的代码并仍然看到不正确的行为来解决问题。尝试找到失败的最简单的例子。
答案 1 :(得分:2)
你的新RoadLine课肯定会导致灾难:
RoadLine::RoadLine(CvPoint* aLine, int aLane){
line = aLine;
lane = aLane;
}
RoadLine::RoadLine(const RoadLine & myRoadLine){
line = myRoadLine.line;
lane = 1;
}
RoadLine::~RoadLine(){
delete line;
}
使用它的代码:
if(lineCount == a){
cvLine(img_final, roadLine[0], roadLine[1], CV_RGB(0,0,255), 3, CV_AA, 0 );
RoadLine myLine = RoadLine(roadLine, 1);//create object on the Stack
roadVector->push_back(myLine); //Push COPY of myLine
cvShowImage("Plate Detection", img_final);
cvWaitKey(0);
}//Stack-based object "myLine" is automatically destroyed here (leaves scope)
自动销毁“myLine”将删除“myLine.line”(在RoadLine的dtor中) 但是“myLine.line”仍然在向量中引用(你只是推了它)。
你必须要做一个DEEP COPY of line(正如其他人建议的那样),如下所示:
RoadLine::RoadLine(const RoadLine & myRoadLine){
line = new CvPoint(*myRoadLine.line);//assuming CvPoint can be copy-constructed
lane = 1;
}
或者使用CvLine对象而不是指针(或其他东西,需要更多上下文)
编辑: Dirk Gently的副本有一个bug,因为它会将内存泄漏给前“行”成员 应该是:
RoadLine& operator=(const RoadLine & o){
if (this != &o) { //Remember to check for self-assignment.
delete []line;//delete[] vs. delete !
line = 0;//if next line throws at least we won't double-delete line
line = new CvPoint[ 2 ]; //this might throw ! should catch (or redesign to get rid of new (prefered)
line[ 0 ] = o.line[ 0 ];
line[ 1 ] = o.line[ 1 ];
lane = o.lane;
}
return *this;
}
//consistent constructor !
RoadLine::RoadLine(CvPoint* aLine, int aLane)
:line(new CvPoint[2]),//might throw, but its better to throw in initializer ! (if you just have one pointer it might be ok to do it like this)
lane(aLane)
{
line[0] = aLine[0];
line[1] = aLine[1];
}
RoadLine::~RoadLine(){
delete[] line;//also use delete[] vs. normal delete here !
}
编辑2:我差点忘了我知道它崩溃的原因!也许你试着建立一对最后和最后+ 1 CvPoint(这显然是假代码)?
CvPoint Pnts[2] = {CvPoint(0,0),CvPoint(1,1)};
Roadline Line(&Pnts[1],1);//tries to access Pnts[2] which is one past end !
答案 2 :(得分:1)
您的RoadLine
班级缺少合适的副本。现在,由于您有一个指向CvPoint
对象的成员,因此每次push_back
时都会创建指针的副本。这可能是不可取的。
RoadLine::RoadLine(const RoadLine & o){
line = new CvPoint[ 2 ];
line[ 0 ] = o.line[ 0 ];
line[ 1 ] = o.line[ 1 ];
lane = o.lane;
}
RoadLine& operator=(const RoadLine & o){
if (this != &o) { //Remember to check for self-assignment.
line = new CvPoint[ 2 ];
line[ 0 ] = o.line[ 0 ];
line[ 1 ] = o.line[ 1 ];
lane = o.lane;
}
return *this;
}
缩短代码:尝试隔离问题:
int main() {
CvPoint pa[] = { CvPoint(0, 0), CvPoint(100, 100) };
RoadLine rl1(pa, 1);
vector<RoadLine> v;
v.push_back(rl1);
return 0;
}
这会崩溃吗?
答案 3 :(得分:1)
使用C ++的诀窍是将“〜”键想象为大号和红色,并且只要按下它就会发出警报声,即。每当你想要在类中添加析构函数时。
如果你要添加一个析构函数,那么你需要一个复制构造函数和赋值运算符。没有例外。即使您不打算复制该对象,您仍应在私有部分声明它们,以便编译器在意外使用时会出错。
每当控制对象的生命周期时,你也应该使用引用计数指针而不是原始的C风格指针(在C ++中 - 说这是“RAII”)。如果你这样做,析构函数将从RoadLine中消失,而且,神奇地,你的问题也会消失。
答案 4 :(得分:1)
你没有指针向量。
std::vector<RoadLine>* roadVector
是指向RoadLine对象矢量的指针。如果你想要一个指针矢量,你应该这样做:
std::vector<RoadLine*> roadVector
这可能对你有帮助(因为向量不会再调用复制构造函数),但是你仍然应该像其他人所建议的那样对它们进行排序。
答案 5 :(得分:0)
这些错误通常是由错误的内存管理引起的。可悲的是,你还没有发布如何管理记忆的方式。
如果你可以在linux系统上运行它,你可以尝试在valgrind下运行你的程序,这有助于追踪不正确的内存访问/释放。不幸的是,valgrind在windows下不可用,但可能有替代品。
答案 6 :(得分:0)
我已将RoadLine的班级定义更改为:
#include <cv.h>
class RoadLine{
private:
int lane;
public:
CvPoint* line;
RoadLine(CvPoint*, int);
RoadLine(const RoadLine &);
~RoadLine();
RoadLine& operator=(const RoadLine & o);
};
RoadLine::RoadLine(CvPoint* aLine, int aLane){
line = aLine;
lane = aLane;
}
RoadLine::RoadLine(const RoadLine & myRoadLine){
line = new CvPoint[ 2 ]; // CRASHES HERE
line[ 0 ] = myRoadLine.line[ 0 ];
line[ 1 ] = myRoadLine.line[ 1 ];
//line = new CvPoint(*myRoadLine.line);
lane = myRoadLine.lane;
}
RoadLine::~RoadLine(){
delete line;
}
RoadLine& RoadLine::operator=(const RoadLine & o){
if (this != &o) { //Remember to check for self-assignment.
line = new CvPoint[ 2 ];
line[ 0 ] = o.line[ 0 ];
line[ 1 ] = o.line[ 1 ];
lane = o.lane;
}
return *this;
}
这是RoadLine类的当前版本
这就是我实现课程的方式:
else{
cvLine(img_final, roadLine[0], roadLine[1], CV_RGB(0,0,255), 3, CV_AA, 0 );
RoadLine myLine(roadLine, 1);
roadVector->push_back(myLine); // FROM HERE
cvShowImage("Plate Detection", img_final);
cvWaitKey(0);
}
当调用push_back时,它会调用复制构造函数,但程序会在上面突出显示的位置崩溃
我的矢量被定义有什么不同;
std::vector<RoadLine>* roadVector
我有一个CvPoint *而不是CvPoint []
对不起,如果这些似乎是非常基本的问题