我道歉,因为这是一个相当棘手的问题,但我无法弄明白这一点。
class View //simplified
{
public:
ROILine* ROI() {return _roi;} //setter does some control stuff...
private:
ROILine *_roi;
}
class ROI : public eq::Object
{
public:
//virtual ROI(ROI* copy) = 0;
virtual ~ROI() {};
virtual uint32_t getType() = 0;
virtual void reset() = 0;
virtual bool addPoint( eq::Vector3f point ) = 0;
virtual bool previewPoint( eq::Vector3f point ) = 0;
virtual bool getNotationLocation( eq::Vector3f& point ) = 0;
virtual bool draw() = 0;
protected:
enum ROIType {
NONE = 0,
LINE,
POLY,
AREA,
VOLUME
};
enum ROIMeasure {
RM_LENGTH = 1,
RM_AREA,
RM_VOLUME,
};
private:
};
class ROILine : virtual public ROI
{
public:
ROILine();
ROILine(ROILine* copy);
ROILine(const ROILine& copy);
virtual ~ROILine() {SFLog(@"Destroying ROILine: 0x%x",this);};
void reset();
float distance() { return _start.distance(_end); }
// ROI Interface
uint32_t getType() { return ROI::LINE; }
virtual bool draw();
bool addPoint( eq::Vector3f point );
bool previewPoint( eq::Vector3f point );
bool getNotationLocation( eq::Vector3f& point );
eq::net::DataOStream& serialize(eq::net::DataOStream& os) ;
eq::net::DataIStream& deserialize(eq::net::DataIStream& is) ;
protected:
enum ROILineState { // RLS_
RLS_RESET,
RLS_START,
RLS_PREVIEW,
RLS_END,
};
private:
uint32_t _state;
eq::Vector3f _start;
eq::Vector3f _end;
};
ROILine::ROILine(const ROILine& copy) : ROI()
{
reset();
switch (copy._state)
{
case RLS_PREVIEW:
case RLS_END:
addPoint(eq::Vector3f(copy._start));
addPoint(eq::Vector3f(copy._end));
break;
case RLS_START:
addPoint(eq::Vector3f(copy._start));
break;
case RLS_RESET:
default:
break;
}
}
/*!
@abstract resets the line values and state
*/
void ROILine::reset()
{
_state = RLS_RESET;
_end = eq::Vector3f::ZERO;
_start = eq::Vector3f::ZERO;
}
/*!
@abstract if it has 2 points, draw the line. (_state > _PREVIEW)
@discussion assumes GL is already set up. Executes drawing commands.
@result true if the line was drawn
*/
bool ROILine::draw()
{
bool retVal = false;
if (_state >= RLS_PREVIEW) {
//glTranslatef(0.0f, 0.0f, -1.0f); //Back Up?
glColor3f( 1.0f, 0.0f, 0.0f ); //Red
glEnable( GL_LINE_SMOOTH );
glLineWidth( 1 );
glBegin( GL_LINES );
{
glVertex3fv( _start.array );
glVertex3fv( _end.array );
}
glEnd();
//glTranslatef(0.0f, 0.0f, 1.0f); // Return
retVal = true;
}
return retVal;
}
// Elsewhere...
View *v = getView(); // returns the view object
// Destroys each time, but works wonderfully
ROILine r = ROILine(*(v->ROI()));
r.draw();
// Does not work (EXC_BAD_ACCESS)
v->ROI()->draw();
// Does not work (EXC_BAD_ACCESS on draw());
ROILine *r = v->ROI();
r->draw(); // debug shows r != 0x0
当我打破r->draw()
并继续时,我得到的错误如下。
[Switching to process 12453]
Current language: auto; currently objective-c++
Warning: the current language does not match this frame.
(gdb) continue
Program received signal: “EXC_BAD_ACCESS”.
"EXC_BAD_ACCESS"
发生r->draw()
或v->ROI()->draw()
它根本没有进入程序,只是暂停而bt
给了我??
< / p>
我的拷贝构造函数工作,因为draw()函数实际上绘制了它应该的位置(而不是!! @#$!4!#@ land)我不知道的是,为什么复制值有效,但是访问v->ROI()->draw()
没有。 必须才能v->ROI()
才能制作副本!!
是? ......不是吗?
很困惑......谢谢,
答案 0 :(得分:1)
我觉得有些奇怪的事情发生了。
你说包含这一行的代码非常有效:
ROILine r = ROILine(*(v->ROI()));
在此行中,您已成功执行*(v->ROI())
。
但是你说如果你尝试做ROILine *r = v->ROI()
那么r的值是NULL。
我认为这些都不是真的(因为这意味着你已成功解除引用NULL指针)。我可以想到两个原因:
此外,确保在执行行设置后验证r为NULL 。有些编译器将指针初始化为NULL,但可能尚未设置。还要检查以确保已关闭优化;有时调试器不能很好地进行优化,这可以使你在认为执行完代码后执行一行代码。
答案 1 :(得分:1)
这些症状听起来像你的ROILine对象已被删除,让你留下一个指向释放内存的悬空指针。当您尝试调用虚函数时,它会崩溃,因为vtable已被覆盖,但是当您使用复制构造函数创建副本时,它至少从释放的对象获取一些有效数据,并且似乎有效。
答案 2 :(得分:1)
假设ROILine
的复制构造函数中的所有内容都正常工作,那么这里有可能:某些东西覆盖了ROILine
返回的View::ROI()
实例的几个字节。
最有可能的是,ROILine
对象的前几个字节包含指向该类的虚函数表的指针。 (至少这是典型的C ++实现所做的。)如果这些字节被覆盖,而不是通过虚函数表调用,程序将最终通过垃圾调用,几乎肯定会崩溃。
但是,在通过复制构造函数创建对象的副本时,根本不会访问指向虚函数表的指针(除非您在复制构造函数中调用虚函数)。在这种情况下,所有数据都会成功复制到具有正确vtable指针的新对象。
由于draw
是vritual,这可以解释为什么在副本上调用它时在原件上调用它不起作用。
如果发生了这种情况,那么您需要弄清楚覆盖ROILine
实例的部分内容。如果该实例是另一个对象的一部分,那么它可能很容易。如果该实例已经单独分配了堆,那么可能会有点困难。
答案 3 :(得分:0)
我认为ROILine应该继承ROI。 在ROILine中绘制虚拟,然后
ROILine * r = v-&gt; ROI(); R-&GT;绘制(); // debug显示r!= 0x0
应该有用......
连接到问题(或不是)调用返回ROI的函数与ROI构造函数完全相同是不好的做法。
(指:ROILine * ROI(){return _roi;} // setter做一些控件......)
也许编译器感到困惑......
答案 4 :(得分:0)
您的复制构造函数在引用时起作用,为此,您需要为其提供一个取消引用(可能为空)的指针。这是语言中有趣的东西之一,因为对引用指针的引用实际上不会取消引用指针,直到你使用引用(C ++真的是多范式,它甚至是懒惰的!)。由于这是未定义的行为,因此只有复制构造函数才有可能。可能在视图中你以某种方式使指针无效。
#include <iostream>
using namespace std;
int addOne(int const & n) {
return n + 1; // Uh oh.
}
int main() {
int * ptr = 0;
cout << addOne(*ptr) << endl; // Doesn't crash here.
return 0;
}